To: vim-dev@vim.org
Subject: Patch 7.2.432
Fcc: outbox
From: Bram Moolenaar <Bram@moolenaar.net>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
------------

Patch 7.2.432
Problem:    When menus are translated they can only be found by the translated
	    name.  That makes ":emenu" difficult to use.
Solution:   Store the untranslated name and use it for completion and :emenu.
	    (Edward L. Fox / Liang Peng / Bezetek James)
Files:	    src/menu.c, src/structs.h


*** ../vim-7.2.431/src/menu.c	2010-05-14 21:19:16.000000000 +0200
--- src/menu.c	2010-05-14 21:52:58.000000000 +0200
***************
*** 58,63 ****
--- 58,66 ----
  static char_u *menutrans_lookup __ARGS((char_u *name, int len));
  #endif
  
+ static char_u *menu_translate_tab_and_shift __ARGS((char_u *arg_start));
+ static void menu_unescape_name  __ARGS((char_u	*p));
+ 
  /* The character for each menu mode */
  static char_u	menu_mode_chars[] = {'n', 'v', 's', 'o', 'i', 'c', 't'};
  
***************
*** 106,115 ****
      int		pri_tab[MENUDEPTH + 1];
      int		enable = MAYBE;	    /* TRUE for "menu enable", FALSE for "menu
  				     * disable */
- #ifdef FEAT_MULTI_LANG
-     char_u	*tofree = NULL;
-     char_u	*new_cmd;
- #endif
  #ifdef FEAT_TOOLBAR
      char_u	*icon = NULL;
  #endif
--- 109,114 ----
***************
*** 251,291 ****
      }
  #endif
  
- #ifdef FEAT_MULTI_LANG
-     /*
-      * Translate menu names as specified with ":menutrans" commands.
-      */
-     menu_path = arg;
-     while (*menu_path)
-     {
- 	/* find the end of one part and check if it should be translated */
- 	p = menu_skip_part(menu_path);
- 	map_to = menutrans_lookup(menu_path, (int)(p - menu_path));
- 	if (map_to != NULL)
- 	{
- 	    /* found a match: replace with the translated part */
- 	    i = (int)STRLEN(map_to);
- 	    new_cmd = alloc((unsigned)STRLEN(arg) + i + 1);
- 	    if (new_cmd == NULL)
- 		break;
- 	    mch_memmove(new_cmd, arg, menu_path - arg);
- 	    mch_memmove(new_cmd + (menu_path - arg), map_to, (size_t)i);
- 	    STRCPY(new_cmd + (menu_path - arg) + i, p);
- 	    p = new_cmd + (menu_path - arg) + i;
- 	    vim_free(tofree);
- 	    tofree = new_cmd;
- 	    arg = new_cmd;
- 	}
- 	if (*p != '.')
- 	    break;
- 	menu_path = p + 1;
-     }
- #endif
- 
-     /*
-      * Isolate the menu name.
-      * Skip the menu name, and translate <Tab> into a real TAB.
-      */
      menu_path = arg;
      if (*menu_path == '.')
      {
--- 250,255 ----
***************
*** 293,313 ****
  	goto theend;
      }
  
!     while (*arg && !vim_iswhite(*arg))
!     {
! 	if ((*arg == '\\' || *arg == Ctrl_V) && arg[1] != NUL)
! 	    arg++;
! 	else if (STRNICMP(arg, "<TAB>", 5) == 0)
! 	{
! 	    *arg = TAB;
! 	    STRMOVE(arg + 1, arg + 5);
! 	}
! 	arg++;
!     }
!     if (*arg != NUL)
! 	*arg++ = NUL;
!     arg = skipwhite(arg);
!     map_to = arg;
  
      /*
       * If there is only a menu name, display menus with that name.
--- 257,263 ----
  	goto theend;
      }
  
!     map_to = menu_translate_tab_and_shift(arg);
  
      /*
       * If there is only a menu name, display menus with that name.
***************
*** 453,463 ****
  #endif
  
  theend:
- #ifdef FEAT_MULTI_LANG
-     vim_free(tofree);
- #else
      ;
- #endif
  }
  
  /*
--- 403,409 ----
***************
*** 498,503 ****
--- 444,453 ----
      int		pri_idx = 0;
      int		old_modes = 0;
      int		amenu;
+ #ifdef FEAT_MULTI_LANG
+     char_u	*en_name;
+     char_u	*map_to = NULL;
+ #endif
  
      /* Make a copy so we can stuff around with it, since it could be const */
      path_name = vim_strsave(menu_path);
***************
*** 511,516 ****
--- 461,476 ----
  	/* Get name of this element in the menu hierarchy, and the simplified
  	 * name (without mnemonic and accelerator text). */
  	next_name = menu_name_skip(name);
+ #ifdef	FEAT_MULTI_LANG
+ 	map_to = menutrans_lookup(name,STRLEN(name));
+ 	if (map_to != NULL)
+ 	{
+ 	    en_name = name;
+ 	    name = map_to;
+ 	}
+ 	else
+ 	    en_name = NULL;
+ #endif
  	dname = menu_text(name, NULL, NULL);
  	if (dname == NULL)
  	    goto erret;
***************
*** 594,599 ****
--- 554,571 ----
  	    menu->name = vim_strsave(name);
  	    /* separate mnemonic and accelerator text from actual menu name */
  	    menu->dname = menu_text(name, &menu->mnemonic, &menu->actext);
+ #ifdef	FEAT_MULTI_LANG
+ 	    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;
+ 	    }
+ #endif
  	    menu->priority = pri_tab[pri_idx];
  	    menu->parent = parent;
  #ifdef FEAT_GUI_MOTIF
***************
*** 1040,1045 ****
--- 1012,1021 ----
      *menup = menu->next;
      vim_free(menu->name);
      vim_free(menu->dname);
+ #ifdef FEAT_MULTI_LANG
+     vim_free(menu->en_name);
+     vim_free(menu->en_dname);
+ #endif
      vim_free(menu->actext);
  #ifdef FEAT_TOOLBAR
      vim_free(menu->iconfile);
***************
*** 1357,1365 ****
--- 1333,1347 ----
  {
      static vimmenu_T	*menu = NULL;
      char_u		*str;
+ #ifdef FEAT_MULTI_LANG
+     static  int		should_advance = FALSE;
+ #endif
  
      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)
***************
*** 1372,1383 ****
  	return NULL;
  
      if (menu->modes & expand_modes)
! 	str = menu->dname;
      else
  	str = (char_u *)"";
  
!     /* Advance to next menu entry. */
!     menu = menu->next;
  
      return str;
  }
--- 1354,1383 ----
  	return NULL;
  
      if (menu->modes & expand_modes)
! #ifdef FEAT_MULTI_LANG
! 	if (should_advance)
! 	    str = menu->en_dname;
! 	else
! 	{
! #endif
! 	    str = menu->dname;
! #ifdef FEAT_MULTI_LANG
! 	    if (menu->en_dname == NULL)
!                 should_advance = TRUE;
! 	}
! #endif
      else
  	str = (char_u *)"";
  
! #ifdef FEAT_MULTI_LANG
!     if (should_advance)
! #endif
!         /* Advance to next menu entry. */
!         menu = menu->next;
! 
! #ifdef FEAT_MULTI_LANG
!     should_advance = !should_advance;
! #endif
  
      return str;
  }
***************
*** 1394,1402 ****
--- 1394,1408 ----
      static vimmenu_T	*menu = NULL;
      static char_u	tbuffer[256]; /*hack*/
      char_u		*str;
+ #ifdef FEAT_MULTI_LANG
+     static  int		should_advance = FALSE;
+ #endif
  
      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
***************
*** 1416,1435 ****
      {
  	if (menu->children != NULL)
  	{
! 	    STRCPY(tbuffer, menu->dname);
  	    /* hack on menu separators:  use a 'magic' char for the separator
  	     * so that '.' in names gets escaped properly */
  	    STRCAT(tbuffer, "\001");
  	    str = tbuffer;
  	}
  	else
! 	    str = menu->dname;
      }
      else
  	str = (char_u *)"";
  
!     /* Advance to next menu entry. */
!     menu = menu->next;
  
      return str;
  }
--- 1422,1472 ----
      {
  	if (menu->children != NULL)
  	{
! #ifdef FEAT_MULTI_LANG
! 	    if (should_advance)
! 		STRCPY(tbuffer, menu->en_dname);
! 	    else
! 	    {
! #endif
! 		STRCPY(tbuffer, menu->dname);
! #ifdef FEAT_MULTI_LANG
! 		if (menu->en_dname == NULL)
! 		    should_advance = TRUE;
! 	    }
! #endif
  	    /* hack on menu separators:  use a 'magic' char for the separator
  	     * so that '.' in names gets escaped properly */
  	    STRCAT(tbuffer, "\001");
  	    str = tbuffer;
  	}
  	else
! #ifdef FEAT_MULTI_LANG
!         {
!             if (should_advance)
!                 str = menu->en_dname;
!             else
!             {
! #endif
!                 str = menu->dname;
! #ifdef FEAT_MULTI_LANG
!                 if (menu->en_dname == NULL)
!                     should_advance = TRUE;
!             }
!         }
! #endif
      }
      else
  	str = (char_u *)"";
  
! #ifdef FEAT_MULTI_LANG
!     if (should_advance)
! #endif
!         /* Advance to next menu entry. */
!         menu = menu->next;
! 
! #ifdef FEAT_MULTI_LANG
!     should_advance = !should_advance;
! #endif
  
      return str;
  }
***************
*** 1469,1475 ****
      char_u	*name;
      vimmenu_T	*menu;
  {
!     return (menu_namecmp(name, menu->name) || menu_namecmp(name, menu->dname));
  }
  
      static int
--- 1506,1516 ----
      char_u	*name;
      vimmenu_T	*menu;
  {
!     if (menu->en_name != NULL
! 	    && (menu_namecmp(name,menu->en_name)
! 		|| menu_namecmp(name,menu->en_dname)))
!         return TRUE;
!     return menu_namecmp(name, menu->name) || menu_namecmp(name, menu->dname);
  }
  
      static int
***************
*** 2402,2407 ****
--- 2443,2452 ----
  		    to = vim_strnsave(to, (int)(arg - to));
  		    if (from_noamp != NULL && to != NULL)
  		    {
+ 			menu_translate_tab_and_shift(from);
+ 			menu_translate_tab_and_shift(to);
+ 			menu_unescape_name(from);
+ 			menu_unescape_name(to);
  			tp[menutrans_ga.ga_len].from = from;
  			tp[menutrans_ga.ga_len].from_noamp = from_noamp;
  			tp[menutrans_ga.ga_len].to = to;
***************
*** 2476,2479 ****
--- 2521,2566 ----
  }
  #endif /* FEAT_MULTI_LANG */
  
+ /*
+  * Unescape the name in the translate dictionary table.
+  */
+     static void
+ menu_unescape_name(name)
+     char_u	*name;
+ {
+     char_u  *p;
+ 
+     for (p = name; *p && *p != '.'; mb_ptr_adv(p))
+ 	if (*p == '\\')
+ 	    STRMOVE(p, p + 1);
+ }
+ 
+ /*
+  * Isolate the menu name.
+  * Skip the menu name, and translate <Tab> into a real TAB.
+  */
+     static char_u *
+ menu_translate_tab_and_shift(arg_start)
+     char_u	*arg_start;
+ {
+     char_u	*arg = arg_start;
+ 
+     while (*arg && !vim_iswhite(*arg))
+     {
+ 	if ((*arg == '\\' || *arg == Ctrl_V) && arg[1] != NUL)
+ 	    arg++;
+ 	else if (STRNICMP(arg, "<TAB>", 5) == 0)
+ 	{
+ 	    *arg = TAB;
+ 	    STRMOVE(arg + 1, arg + 5);
+ 	}
+ 	arg++;
+     }
+     if (*arg != NUL)
+ 	*arg++ = NUL;
+     arg = skipwhite(arg);
+ 
+     return arg;
+ }
+ 
  #endif /* FEAT_MENU */
*** ../vim-7.2.431/src/structs.h	2009-09-18 17:24:54.000000000 +0200
--- src/structs.h	2010-05-14 22:21:50.000000000 +0200
***************
*** 232,238 ****
  {
      wininfo_T	*wi_next;	/* next entry or NULL for last entry */
      wininfo_T	*wi_prev;	/* previous entry or NULL for first entry */
!     win_T	*wi_win;	/* pointer to window that did set wi_lnum */
      pos_T	wi_fpos;	/* last cursor position in the file */
      int		wi_optset;	/* TRUE when wi_opt has useful values */
      winopt_T	wi_opt;		/* local window options */
--- 232,238 ----
  {
      wininfo_T	*wi_next;	/* next entry or NULL for last entry */
      wininfo_T	*wi_prev;	/* previous entry or NULL for first entry */
!     win_T	*wi_win;	/* pointer to window that did set wi_fpos */
      pos_T	wi_fpos;	/* last cursor position in the file */
      int		wi_optset;	/* TRUE when wi_opt has useful values */
      winopt_T	wi_opt;		/* local window options */
***************
*** 2207,2214 ****
  {
      int		modes;		    /* Which modes is this menu visible for? */
      int		enabled;	    /* for which modes the menu is enabled */
!     char_u	*name;		    /* Name of menu */
!     char_u	*dname;		    /* Displayed Name (without '&') */
      int		mnemonic;	    /* mnemonic key (after '&') */
      char_u	*actext;	    /* accelerator text (after TAB) */
      int		priority;	    /* Menu order priority */
--- 2207,2220 ----
  {
      int		modes;		    /* Which modes is this menu visible for? */
      int		enabled;	    /* for which modes the menu is enabled */
!     char_u	*name;		    /* Name of menu, possibly translated */
!     char_u	*dname;		    /* Displayed Name ("name" without '&') */
! #ifdef FEAT_MULTI_LANG
!     char_u	*en_name;	    /* "name" untranslated, NULL when "name"
! 				     * was not translated */
!     char_u	*en_dname;	    /* "dname" untranslated, NULL when "dname"
! 				     * was not translated */
! #endif
      int		mnemonic;	    /* mnemonic key (after '&') */
      char_u	*actext;	    /* accelerator text (after TAB) */
      int		priority;	    /* Menu order priority */
*** ../vim-7.2.431/src/version.c	2010-05-14 21:19:16.000000000 +0200
--- src/version.c	2010-05-14 22:19:39.000000000 +0200
***************
*** 683,684 ****
--- 683,686 ----
  {   /* Add new patch number below this line */
+ /**/
+     432,
  /**/

-- 
It is hard to understand how a cemetery raised its burial
cost and blamed it on the cost of living.

 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\        download, build and distribute -- http://www.A-A-P.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///
