Ejemplo n.º 1
0
/*
 * Duplicate the menu item text and then process to see if a mnemonic key
 * and/or accelerator text has been identified.
 * Returns a pointer to allocated memory, or NULL for failure.
 * If mnemonic != NULL, *mnemonic is set to the character after the first '&'.
 * If actext != NULL, *actext is set to the text after the first TAB.
 */
static char_u *menu_text(char_u *str, int *mnemonic, char_u **actext)
{
  char_u      *p;
  char_u      *text;

  /* Locate accelerator text, after the first TAB */
  p = vim_strchr(str, TAB);
  if (p != NULL) {
    if (actext != NULL)
      *actext = vim_strsave(p + 1);
    text = vim_strnsave(str, (int)(p - str));
  } else
    text = vim_strsave(str);

  /* Find mnemonic characters "&a" and reduce "&&" to "&". */
  for (p = text; p != NULL; ) {
    p = vim_strchr(p, '&');
    if (p != NULL) {
      if (p[1] == NUL)              /* trailing "&" */
        break;
      if (mnemonic != NULL && p[1] != '&')
        *mnemonic = p[1];
      STRMOVE(p, p + 1);
      p = p + 1;
    }
  }
  return text;
}
Ejemplo n.º 2
0
    static char *
strerror_win32(int eno)
{
    static LPVOID msgbuf = NULL;
    char_u *ptr;

    if (msgbuf)
	LocalFree(msgbuf);
    FormatMessage(
	FORMAT_MESSAGE_ALLOCATE_BUFFER |
	FORMAT_MESSAGE_FROM_SYSTEM |
	FORMAT_MESSAGE_IGNORE_INSERTS,
	NULL,
	eno,
	MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
	(LPTSTR) &msgbuf,
	0,
	NULL);
    /* chomp \r or \n */
    for (ptr = (char_u *)msgbuf; *ptr; ptr++)
	switch (*ptr)
	{
	    case '\r':
		STRMOVE(ptr, ptr + 1);
		ptr--;
		break;
	    case '\n':
		if (*(ptr + 1) == '\0')
		    *ptr = '\0';
		else
		    *ptr = ' ';
		break;
	}
    return msgbuf;
}
Ejemplo n.º 3
0
/*
 * Unescape the name in the translate dictionary table.
 */
static void menu_unescape_name(char_u *name)
{
  char_u  *p;

  for (p = name; *p && *p != '.'; mb_ptr_adv(p))
    if (*p == '\\')
      STRMOVE(p, p + 1);
}
Ejemplo n.º 4
0
Archivo: sign.c Proyecto: Snaptags/vim
/*
 * Initialize the text for a new sign
 */
    static int
sign_define_init_text(sign_T *sp, char_u *text)
{
    char_u	*s;
    char_u	*endp;
    int		cells;
    int		len;

    endp = text + (int)STRLEN(text);

    // Remove backslashes so that it is possible to use a space.
    for (s = text; s + 1 < endp; ++s)
	if (*s == '\\')
	{
	    STRMOVE(s, s + 1);
	    --endp;
	}

    // Count cells and check for non-printable chars
    if (has_mbyte)
    {
	cells = 0;
	for (s = text; s < endp; s += (*mb_ptr2len)(s))
	{
	    if (!vim_isprintc((*mb_ptr2char)(s)))
		break;
	    cells += (*mb_ptr2cells)(s);
	}
    }
    else
    {
	for (s = text; s < endp; ++s)
	    if (!vim_isprintc(*s))
		break;
	cells = (int)(s - text);
    }

    // Currently sign text must be one or two display cells
    if (s != endp || cells < 1 || cells > 2)
    {
	semsg(_("E239: Invalid sign text: %s"), text);
	return FAIL;
    }

    vim_free(sp->sn_text);
    // Allocate one byte more if we need to pad up
    // with a space.
    len = (int)(endp - text + ((cells == 1) ? 1 : 0));
    sp->sn_text = vim_strnsave(text, len);

    // For single character sign text, pad with a space.
    if (sp->sn_text != NULL && cells == 1)
	STRCPY(sp->sn_text + len - 1, " ");

    return OK;
}
Ejemplo n.º 5
0
/*
 * Skip over this element of the menu path and return the start of the next
 * element.  Any \ and ^Vs are removed from the current element.
 * "name" may be modified.
 */
char_u *menu_name_skip(char_u *name)
{
  char_u  *p;

  for (p = name; *p && *p != '.'; mb_ptr_adv(p)) {
    if (*p == '\\' || *p == Ctrl_V) {
      STRMOVE(p, p + 1);
      if (*p == NUL)
        break;
    }
  }
  if (*p)
    *p++ = NUL;
  return p;
}
Ejemplo n.º 6
0
/*
 * Isolate the menu name.
 * Skip the menu name, and translate <Tab> into a real TAB.
 */
static char_u *menu_translate_tab_and_shift(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;
}
Ejemplo n.º 7
0
/*
 * Duplicate the menu item text and then process to see if a mnemonic key
 * and/or accelerator text has been identified.
 * Returns a pointer to allocated memory, or NULL for failure.
 * If mnemonic != NULL, *mnemonic is set to the character after the first '&'.
 * If actext != NULL, *actext is set to the text after the first TAB.
 */
static char_u *menu_text(char_u *str, int *mnemonic, char_u **actext)
{
  char_u      *p;
  char_u      *text;

  /* Locate accelerator text, after the first TAB */
  p = vim_strchr(str, TAB);
  if (p != NULL) {
    if (actext != NULL)
      *actext = vim_strsave(p + 1);
    text = vim_strnsave(str, (int)(p - str));
  } else
    text = vim_strsave(str);

  /* Find mnemonic characters "&a" and reduce "&&" to "&". */
  for (p = text; p != NULL; ) {
    p = vim_strchr(p, '&');
    if (p != NULL) {
      if (p[1] == NUL)              /* trailing "&" */
        break;
      if (mnemonic != NULL && p[1] != '&')
#if !defined(__MVS__) || defined(MOTIF390_MNEMONIC_FIXED)
        *mnemonic = p[1];
#else
      {
        /*
         * Well there is a bug in the Motif libraries on OS390 Unix.
         * The mnemonic keys needs to be converted to ASCII values
         * first.
         * This behavior has been seen in 2.8 and 2.9.
         */
        char c = p[1];
        __etoa_l(&c, 1);
        *mnemonic = c;
      }
#endif
      STRMOVE(p, p + 1);
      p = p + 1;
    }
  }
  return text;
}
Ejemplo n.º 8
0
/*
 * Get the stopdir string.  Check that ';' is not escaped.
 */
char_u *vim_findfile_stopdir(char_u *buf)
{
  char_u      *r_ptr = buf;

  while (*r_ptr != NUL && *r_ptr != ';') {
    if (r_ptr[0] == '\\' && r_ptr[1] == ';') {
      /* Overwrite the escape char,
       * use STRLEN(r_ptr) to move the trailing '\0'. */
      STRMOVE(r_ptr, r_ptr + 1);
      r_ptr++;
    }
    r_ptr++;
  }
  if (*r_ptr == ';') {
    *r_ptr = 0;
    r_ptr++;
  } else if (*r_ptr == NUL)
    r_ptr = NULL;
  return r_ptr;
}
Ejemplo n.º 9
0
/*
 * Find a file in a search context.
 * The search context was created with vim_findfile_init() above.
 * Return a pointer to an allocated file name or NULL if nothing found.
 * To get all matching files call this function until you get NULL.
 *
 * If the passed search_context is NULL, NULL is returned.
 *
 * The search algorithm is depth first. To change this replace the
 * stack with a list (don't forget to leave partly searched directories on the
 * top of the list).
 */
char_u *vim_findfile(void *search_ctx_arg)
{
  char_u      *file_path;
  char_u      *rest_of_wildcards;
  char_u      *path_end = NULL;
  ff_stack_T  *stackp;
  int len;
  int i;
  char_u      *p;
  char_u      *suf;
  ff_search_ctx_T *search_ctx;

  if (search_ctx_arg == NULL)
    return NULL;

  search_ctx = (ff_search_ctx_T *)search_ctx_arg;

  /*
   * filepath is used as buffer for various actions and as the storage to
   * return a found filename.
   */
  file_path = xmalloc(MAXPATHL);

  /* store the end of the start dir -- needed for upward search */
  if (search_ctx->ffsc_start_dir != NULL)
    path_end = &search_ctx->ffsc_start_dir[
      STRLEN(search_ctx->ffsc_start_dir)];

  /* upward search loop */
  for (;; ) {
    /* downward search loop */
    for (;; ) {
      /* check if user user wants to stop the search*/
      ui_breakcheck();
      if (got_int)
        break;

      /* get directory to work on from stack */
      stackp = ff_pop(search_ctx);
      if (stackp == NULL)
        break;

      /*
       * TODO: decide if we leave this test in
       *
       * GOOD: don't search a directory(-tree) twice.
       * BAD:  - check linked list for every new directory entered.
       *       - check for double files also done below
       *
       * Here we check if we already searched this directory.
       * We already searched a directory if:
       * 1) The directory is the same.
       * 2) We would use the same wildcard string.
       *
       * Good if you have links on same directory via several ways
       *  or you have selfreferences in directories (e.g. SuSE Linux 6.3:
       *  /etc/rc.d/init.d is linked to /etc/rc.d -> endless loop)
       *
       * This check is only needed for directories we work on for the
       * first time (hence stackp->ff_filearray == NULL)
       */
      if (stackp->ffs_filearray == NULL
          && ff_check_visited(&search_ctx->ffsc_dir_visited_list
              ->ffvl_visited_list,
              stackp->ffs_fix_path
              , stackp->ffs_wc_path
              ) == FAIL) {
#ifdef FF_VERBOSE
        if (p_verbose >= 5) {
          verbose_enter_scroll();
          smsg((char_u *)"Already Searched: %s (%s)",
              stackp->ffs_fix_path, stackp->ffs_wc_path);
          /* don't overwrite this either */
          msg_puts((char_u *)"\n");
          verbose_leave_scroll();
        }
#endif
        ff_free_stack_element(stackp);
        continue;
      }
#ifdef FF_VERBOSE
      else if (p_verbose >= 5) {
        verbose_enter_scroll();
        smsg((char_u *)"Searching: %s (%s)",
            stackp->ffs_fix_path, stackp->ffs_wc_path);
        /* don't overwrite this either */
        msg_puts((char_u *)"\n");
        verbose_leave_scroll();
      }
#endif

      /* check depth */
      if (stackp->ffs_level <= 0) {
        ff_free_stack_element(stackp);
        continue;
      }

      file_path[0] = NUL;

      /*
       * If no filearray till now expand wildcards
       * The function expand_wildcards() can handle an array of paths
       * and all possible expands are returned in one array. We use this
       * to handle the expansion of '**' into an empty string.
       */
      if (stackp->ffs_filearray == NULL) {
        char_u *dirptrs[2];

        /* we use filepath to build the path expand_wildcards() should
         * expand.
         */
        dirptrs[0] = file_path;
        dirptrs[1] = NULL;

        /* if we have a start dir copy it in */
        if (!vim_isAbsName(stackp->ffs_fix_path)
            && search_ctx->ffsc_start_dir) {
          STRCPY(file_path, search_ctx->ffsc_start_dir);
          add_pathsep(file_path);
        }

        /* append the fix part of the search path */
        STRCAT(file_path, stackp->ffs_fix_path);
        add_pathsep(file_path);

        rest_of_wildcards = stackp->ffs_wc_path;
        if (*rest_of_wildcards != NUL) {
          len = (int)STRLEN(file_path);
          if (STRNCMP(rest_of_wildcards, "**", 2) == 0) {
            /* pointer to the restrict byte
             * The restrict byte is not a character!
             */
            p = rest_of_wildcards + 2;

            if (*p > 0) {
              (*p)--;
              file_path[len++] = '*';
            }

            if (*p == 0) {
              /* remove '**<numb> from wildcards */
              STRMOVE(rest_of_wildcards, rest_of_wildcards + 3);
            } else
              rest_of_wildcards += 3;

            if (stackp->ffs_star_star_empty == 0) {
              /* if not done before, expand '**' to empty */
              stackp->ffs_star_star_empty = 1;
              dirptrs[1] = stackp->ffs_fix_path;
            }
          }

          /*
           * Here we copy until the next path separator or the end of
           * the path. If we stop at a path separator, there is
           * still something else left. This is handled below by
           * pushing every directory returned from expand_wildcards()
           * on the stack again for further search.
           */
          while (*rest_of_wildcards
                 && !vim_ispathsep(*rest_of_wildcards))
            file_path[len++] = *rest_of_wildcards++;

          file_path[len] = NUL;
          if (vim_ispathsep(*rest_of_wildcards))
            rest_of_wildcards++;
        }

        /*
         * Expand wildcards like "*" and "$VAR".
         * If the path is a URL don't try this.
         */
        if (path_with_url(dirptrs[0])) {
          stackp->ffs_filearray = (char_u **)xmalloc(sizeof(char *));
          stackp->ffs_filearray[0] = vim_strsave(dirptrs[0]);
          stackp->ffs_filearray_size = 1;
        } else
          /* Add EW_NOTWILD because the expanded path may contain
           * wildcard characters that are to be taken literally.
           * This is a bit of a hack. */
          expand_wildcards((dirptrs[1] == NULL) ? 1 : 2, dirptrs,
              &stackp->ffs_filearray_size,
              &stackp->ffs_filearray,
              EW_DIR|EW_ADDSLASH|EW_SILENT|EW_NOTWILD);

        stackp->ffs_filearray_cur = 0;
        stackp->ffs_stage = 0;
      } else
        rest_of_wildcards = &stackp->ffs_wc_path[
          STRLEN(stackp->ffs_wc_path)];

      if (stackp->ffs_stage == 0) {
        /* this is the first time we work on this directory */
        if (*rest_of_wildcards == NUL) {
          /*
           * We don't have further wildcards to expand, so we have to
           * check for the final file now.
           */
          for (i = stackp->ffs_filearray_cur;
               i < stackp->ffs_filearray_size; ++i) {
            if (!path_with_url(stackp->ffs_filearray[i])
                && !os_isdir(stackp->ffs_filearray[i]))
              continue;                 /* not a directory */

            /* prepare the filename to be checked for existence
             * below */
            STRCPY(file_path, stackp->ffs_filearray[i]);
            add_pathsep(file_path);
            STRCAT(file_path, search_ctx->ffsc_file_to_search);

            /*
             * Try without extra suffix and then with suffixes
             * from 'suffixesadd'.
             */
            len = (int)STRLEN(file_path);
            if (search_ctx->ffsc_tagfile)
              suf = (char_u *)"";
            else
              suf = curbuf->b_p_sua;
            for (;; ) {
              /* if file exists and we didn't already find it */
              if ((path_with_url(file_path)
                   || (os_file_exists(file_path)
                       && (search_ctx->ffsc_find_what
                           == FINDFILE_BOTH
                           || ((search_ctx->ffsc_find_what
                                == FINDFILE_DIR)
                               == os_isdir(file_path)))))
#ifndef FF_VERBOSE
                  && (ff_check_visited(
                          &search_ctx->ffsc_visited_list->ffvl_visited_list,
                          file_path
                          , (char_u *)""
                          ) == OK)
#endif
                  ) {
#ifdef FF_VERBOSE
                if (ff_check_visited(
                        &search_ctx->ffsc_visited_list->ffvl_visited_list,
                        file_path
                        , (char_u *)""
                        ) == FAIL) {
                  if (p_verbose >= 5) {
                    verbose_enter_scroll();
                    smsg((char_u *)"Already: %s",
                        file_path);
                    /* don't overwrite this either */
                    msg_puts((char_u *)"\n");
                    verbose_leave_scroll();
                  }
                  continue;
                }
#endif

                /* push dir to examine rest of subdirs later */
                stackp->ffs_filearray_cur = i + 1;
                ff_push(search_ctx, stackp);

                if (!path_with_url(file_path))
                  simplify_filename(file_path);
                if (os_dirname(ff_expand_buffer, MAXPATHL)
                    == OK) {
                  p = path_shorten_fname(file_path,
                      ff_expand_buffer);
                  if (p != NULL)
                    STRMOVE(file_path, p);
                }
#ifdef FF_VERBOSE
                if (p_verbose >= 5) {
                  verbose_enter_scroll();
                  smsg((char_u *)"HIT: %s", file_path);
                  /* don't overwrite this either */
                  msg_puts((char_u *)"\n");
                  verbose_leave_scroll();
                }
#endif
                return file_path;
              }

              /* Not found or found already, try next suffix. */
              if (*suf == NUL)
                break;
              copy_option_part(&suf, file_path + len,
                  MAXPATHL - len, ",");
            }
          }
        } else {
          /*
           * still wildcards left, push the directories for further
           * search
           */
          for (i = stackp->ffs_filearray_cur;
               i < stackp->ffs_filearray_size; ++i) {
            if (!os_isdir(stackp->ffs_filearray[i]))
              continue;                 /* not a directory */

            ff_push(search_ctx,
                ff_create_stack_element(
                    stackp->ffs_filearray[i],
                    rest_of_wildcards,
                    stackp->ffs_level - 1, 0));
          }
        }
        stackp->ffs_filearray_cur = 0;
        stackp->ffs_stage = 1;
      }

      /*
       * if wildcards contains '**' we have to descent till we reach the
       * leaves of the directory tree.
       */
      if (STRNCMP(stackp->ffs_wc_path, "**", 2) == 0) {
        for (i = stackp->ffs_filearray_cur;
             i < stackp->ffs_filearray_size; ++i) {
          if (fnamecmp(stackp->ffs_filearray[i],
                  stackp->ffs_fix_path) == 0)
            continue;             /* don't repush same directory */
          if (!os_isdir(stackp->ffs_filearray[i]))
            continue;               /* not a directory */
          ff_push(search_ctx,
              ff_create_stack_element(stackp->ffs_filearray[i],
                  stackp->ffs_wc_path, stackp->ffs_level - 1, 1));
        }
      }

      /* we are done with the current directory */
      ff_free_stack_element(stackp);

    }

    /* If we reached this, we didn't find anything downwards.
     * Let's check if we should do an upward search.
     */
    if (search_ctx->ffsc_start_dir
        && search_ctx->ffsc_stopdirs_v != NULL && !got_int) {
      ff_stack_T  *sptr;

      /* is the last starting directory in the stop list? */
      if (ff_path_in_stoplist(search_ctx->ffsc_start_dir,
              (int)(path_end - search_ctx->ffsc_start_dir),
              search_ctx->ffsc_stopdirs_v) == TRUE)
        break;

      /* cut of last dir */
      while (path_end > search_ctx->ffsc_start_dir
             && vim_ispathsep(*path_end))
        path_end--;
      while (path_end > search_ctx->ffsc_start_dir
             && !vim_ispathsep(path_end[-1]))
        path_end--;
      *path_end = 0;
      path_end--;

      if (*search_ctx->ffsc_start_dir == 0)
        break;

      STRCPY(file_path, search_ctx->ffsc_start_dir);
      add_pathsep(file_path);
      STRCAT(file_path, search_ctx->ffsc_fix_path);

      /* create a new stack entry */
      sptr = ff_create_stack_element(file_path,
          search_ctx->ffsc_wc_path, search_ctx->ffsc_level, 0);
      ff_push(search_ctx, sptr);
    } else
      break;
  }

  free(file_path);
  return NULL;
}
Ejemplo n.º 10
0
/// Convert the string "str[orglen]" to do ignore-case comparing.  Uses the
/// current locale.
///
/// When "buf" is NULL returns an allocated string (NULL for out-of-memory).
/// Otherwise puts the result in "buf[buflen]".
///
/// @param str
/// @param orglen
/// @param buf
/// @param buflen
///
/// @return converted string.
char_u* str_foldcase(char_u *str, int orglen, char_u *buf, int buflen)
{
  garray_T ga;
  int i;
  int len = orglen;

#define GA_CHAR(i) ((char_u *)ga.ga_data)[i]
#define GA_PTR(i) ((char_u *)ga.ga_data + i)
#define STR_CHAR(i) (buf == NULL ? GA_CHAR(i) : buf[i])
#define STR_PTR(i) (buf == NULL ? GA_PTR(i) : buf + i)

  // Copy "str" into "buf" or allocated memory, unmodified.
  if (buf == NULL) {
    ga_init(&ga, 1, 10);

    if (ga_grow(&ga, len + 1) == FAIL) {
      return NULL;
    }
    memmove(ga.ga_data, str, (size_t)len);
    ga.ga_len = len;
  } else {
    if (len >= buflen) {
      // Ugly!
      len = buflen - 1;
    }
    memmove(buf, str, (size_t)len);
  }

  if (buf == NULL) {
    GA_CHAR(len) = NUL;
  } else {
    buf[len] = NUL;
  }

  // Make each character lower case.
  i = 0;
  while (STR_CHAR(i) != NUL) {
    if (enc_utf8 || (has_mbyte && (MB_BYTE2LEN(STR_CHAR(i)) > 1))) {
      if (enc_utf8) {
        int c = utf_ptr2char(STR_PTR(i));
        int olen = utf_ptr2len(STR_PTR(i));
        int lc = utf_tolower(c);

        // Only replace the character when it is not an invalid
        // sequence (ASCII character or more than one byte) and
        // utf_tolower() doesn't return the original character.
        if (((c < 0x80) || (olen > 1)) && (c != lc)) {
          int nlen = utf_char2len(lc);

          // If the byte length changes need to shift the following
          // characters forward or backward.
          if (olen != nlen) {
            if (nlen > olen) {
              if ((buf == NULL)
                  ? (ga_grow(&ga, nlen - olen + 1) == FAIL)
                  : (len + nlen - olen >= buflen)) {
                // out of memory, keep old char
                lc = c;
                nlen = olen;
              }
            }

            if (olen != nlen) {
              if (buf == NULL) {
                STRMOVE(GA_PTR(i) + nlen, GA_PTR(i) + olen);
                ga.ga_len += nlen - olen;
              } else {
                STRMOVE(buf + i + nlen, buf + i + olen);
                len += nlen - olen;
              }
            }
          }
          (void)utf_char2bytes(lc, STR_PTR(i));
        }
      }

      // skip to next multi-byte char
      i += (*mb_ptr2len)(STR_PTR(i));
    } else {
      if (buf == NULL) {
        GA_CHAR(i) = TOLOWER_LOC(GA_CHAR(i));
      } else {
        buf[i] = TOLOWER_LOC(buf[i]);
      }
      ++i;
    }
  }

  if (buf == NULL) {
    return (char_u *)ga.ga_data;
  }
  return buf;
}
Ejemplo n.º 11
0
/*
 * Do the :menu command and relatives.
 */
void 
ex_menu (
    exarg_T *eap                   /* Ex command arguments */
)
{
  char_u      *menu_path;
  int modes;
  char_u      *map_to;
  int noremap;
  int silent = FALSE;
  int special = FALSE;
  int unmenu;
  char_u      *map_buf;
  char_u      *arg;
  char_u      *p;
  int i;
  int pri_tab[MENUDEPTH + 1];
  int enable = MAYBE;               /* TRUE for "menu enable", FALSE for "menu
                                     * disable */
  vimmenu_T menuarg;

  modes = get_menu_cmd_modes(eap->cmd, eap->forceit, &noremap, &unmenu);
  arg = eap->arg;

  for (;; ) {
    if (STRNCMP(arg, "<script>", 8) == 0) {
      noremap = REMAP_SCRIPT;
      arg = skipwhite(arg + 8);
      continue;
    }
    if (STRNCMP(arg, "<silent>", 8) == 0) {
      silent = TRUE;
      arg = skipwhite(arg + 8);
      continue;
    }
    if (STRNCMP(arg, "<special>", 9) == 0) {
      special = TRUE;
      arg = skipwhite(arg + 9);
      continue;
    }
    break;
  }


  /* Locate an optional "icon=filename" argument. */
  if (STRNCMP(arg, "icon=", 5) == 0) {
    arg += 5;
    while (*arg != NUL && *arg != ' ') {
      if (*arg == '\\')
        STRMOVE(arg, arg + 1);
      mb_ptr_adv(arg);
    }
    if (*arg != NUL) {
      *arg++ = NUL;
      arg = skipwhite(arg);
    }
  }

  /*
   * Fill in the priority table.
   */
  for (p = arg; *p; ++p)
    if (!VIM_ISDIGIT(*p) && *p != '.')
      break;
  if (vim_iswhite(*p)) {
    for (i = 0; i < MENUDEPTH && !vim_iswhite(*arg); ++i) {
      pri_tab[i] = getdigits_int(&arg);
      if (pri_tab[i] == 0)
        pri_tab[i] = 500;
      if (*arg == '.')
        ++arg;
    }
    arg = skipwhite(arg);
  } else if (eap->addr_count && eap->line2 != 0) {
    pri_tab[0] = eap->line2;
    i = 1;
  } else
    i = 0;
  while (i < MENUDEPTH)
    pri_tab[i++] = 500;
  pri_tab[MENUDEPTH] = -1;              /* mark end of the table */

  /*
   * Check for "disable" or "enable" argument.
   */
  if (STRNCMP(arg, "enable", 6) == 0 && vim_iswhite(arg[6])) {
    enable = TRUE;
    arg = skipwhite(arg + 6);
  } else if (STRNCMP(arg, "disable", 7) == 0 && vim_iswhite(arg[7])) {
    enable = FALSE;
    arg = skipwhite(arg + 7);
  }

  /*
   * If there is no argument, display all menus.
   */
  if (*arg == NUL) {
    show_menus(arg, modes);
    return;
  }


  menu_path = arg;
  if (*menu_path == '.') {
    EMSG2(_(e_invarg2), menu_path);
    goto theend;
  }

  map_to = menu_translate_tab_and_shift(arg);

  /*
   * If there is only a menu name, display menus with that name.
   */
  if (*map_to == NUL && !unmenu && enable == MAYBE) {
    show_menus(menu_path, modes);
    goto theend;
  } else if (*map_to != NUL && (unmenu || enable != MAYBE)) {
    EMSG(_(e_trailing));
    goto theend;
  }

  if (enable != MAYBE) {
    /*
     * Change sensitivity of the menu.
     * For the PopUp menu, remove a menu for each mode separately.
     * Careful: menu_nable_recurse() changes menu_path.
     */
    if (STRCMP(menu_path, "*") == 0)            /* meaning: do all menus */
      menu_path = (char_u *)"";

    if (menu_is_popup(menu_path)) {
      for (i = 0; i < MENU_INDEX_TIP; ++i)
        if (modes & (1 << i)) {
          p = popup_mode_name(menu_path, i);
          menu_nable_recurse(root_menu, p, MENU_ALL_MODES, enable);
          free(p);
        }
    }
    menu_nable_recurse(root_menu, menu_path, modes, enable);
  } else if (unmenu) {
    /*
     * Delete menu(s).
     */
    if (STRCMP(menu_path, "*") == 0)            /* meaning: remove all menus */
      menu_path = (char_u *)"";

    /*
     * For the PopUp menu, remove a menu for each mode separately.
     */
    if (menu_is_popup(menu_path)) {
      for (i = 0; i < MENU_INDEX_TIP; ++i)
        if (modes & (1 << i)) {
          p = popup_mode_name(menu_path, i);
          remove_menu(&root_menu, p, MENU_ALL_MODES, TRUE);
          free(p);
        }
    }

    /* Careful: remove_menu() changes menu_path */
    remove_menu(&root_menu, menu_path, modes, FALSE);
  } else {
    /*
     * Add menu(s).
     * Replace special key codes.
     */
    if (STRICMP(map_to, "<nop>") == 0) {        /* "<Nop>" means nothing */
      map_to = (char_u *)"";
      map_buf = NULL;
    } else if (modes & MENU_TIP_MODE)
      map_buf = NULL;           /* Menu tips are plain text. */
    else
      map_to = replace_termcodes(map_to, &map_buf, FALSE, TRUE, special);
    menuarg.modes = modes;
    menuarg.noremap[0] = noremap;
    menuarg.silent[0] = silent;
    add_menu_path(menu_path, &menuarg, pri_tab, map_to
        );

    /*
     * For the PopUp menu, add a menu for each mode separately.
     */
    if (menu_is_popup(menu_path)) {
      for (i = 0; i < MENU_INDEX_TIP; ++i)
        if (modes & (1 << i)) {
          p = popup_mode_name(menu_path, i);
          // Include all modes, to make ":amenu" work
          menuarg.modes = modes;
          add_menu_path(p, &menuarg, pri_tab, map_to);
          free(p);
        }
    }

    free(map_buf);
  }


theend:
  ;
}
Ejemplo n.º 12
0
/*
 * Convert the string "str[orglen]" to do ignore-case comparing.  Uses the
 * current locale.
 * When "buf" is NULL returns an allocated string (NULL for out-of-memory).
 * Otherwise puts the result in "buf[buflen]".
 */
    char_u *
str_foldcase(
    char_u	*str,
    int		orglen,
    char_u	*buf,
    int		buflen)
{
    garray_T	ga;
    int		i;
    int		len = orglen;

#define GA_CHAR(i)  ((char_u *)ga.ga_data)[i]
#define GA_PTR(i)   ((char_u *)ga.ga_data + i)
#define STR_CHAR(i)  (buf == NULL ? GA_CHAR(i) : buf[i])
#define STR_PTR(i)   (buf == NULL ? GA_PTR(i) : buf + i)

    /* Copy "str" into "buf" or allocated memory, unmodified. */
    if (buf == NULL)
    {
	ga_init2(&ga, 1, 10);
	if (ga_grow(&ga, len + 1) == FAIL)
	    return NULL;
	mch_memmove(ga.ga_data, str, (size_t)len);
	ga.ga_len = len;
    }
    else
    {
	if (len >= buflen)	    /* Ugly! */
	    len = buflen - 1;
	mch_memmove(buf, str, (size_t)len);
    }
    if (buf == NULL)
	GA_CHAR(len) = NUL;
    else
	buf[len] = NUL;

    /* Make each character lower case. */
    i = 0;
    while (STR_CHAR(i) != NUL)
    {
#ifdef FEAT_MBYTE
	if (enc_utf8 || (has_mbyte && MB_BYTE2LEN(STR_CHAR(i)) > 1))
	{
	    if (enc_utf8)
	    {
		int	c = utf_ptr2char(STR_PTR(i));
		int	olen = utf_ptr2len(STR_PTR(i));
		int	lc = utf_tolower(c);

		/* Only replace the character when it is not an invalid
		 * sequence (ASCII character or more than one byte) and
		 * utf_tolower() doesn't return the original character. */
		if ((c < 0x80 || olen > 1) && c != lc)
		{
		    int	    nlen = utf_char2len(lc);

		    /* If the byte length changes need to shift the following
		     * characters forward or backward. */
		    if (olen != nlen)
		    {
			if (nlen > olen)
			{
			    if (buf == NULL
				    ? ga_grow(&ga, nlen - olen + 1) == FAIL
				    : len + nlen - olen >= buflen)
			    {
				/* out of memory, keep old char */
				lc = c;
				nlen = olen;
			    }
			}
			if (olen != nlen)
			{
			    if (buf == NULL)
			    {
				STRMOVE(GA_PTR(i) + nlen, GA_PTR(i) + olen);
				ga.ga_len += nlen - olen;
			    }
			    else
			    {
				STRMOVE(buf + i + nlen, buf + i + olen);
				len += nlen - olen;
			    }
			}
		    }
		    (void)utf_char2bytes(lc, STR_PTR(i));
		}
	    }
	    /* skip to next multi-byte char */
	    i += (*mb_ptr2len)(STR_PTR(i));
	}
	else
#endif
	{
	    if (buf == NULL)
		GA_CHAR(i) = TOLOWER_LOC(GA_CHAR(i));
	    else
		buf[i] = TOLOWER_LOC(buf[i]);
	    ++i;
	}
    }

    if (buf == NULL)
	return (char_u *)ga.ga_data;
    return buf;
}