From afce081b90c1e2c50c3507758c7558a0dfa1f33e Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 15:18:03 +0200 Subject: Adding upstream version 2:8.2.2434. Signed-off-by: Daniel Baumann --- src/map.c | 2750 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2750 insertions(+) create mode 100644 src/map.c (limited to 'src/map.c') diff --git a/src/map.c b/src/map.c new file mode 100644 index 0000000..917f1a2 --- /dev/null +++ b/src/map.c @@ -0,0 +1,2750 @@ +/* vi:set ts=8 sts=4 sw=4 noet: + * + * VIM - Vi IMproved by Bram Moolenaar + * + * Do ":help uganda" in Vim to read copying and usage conditions. + * Do ":help credits" in Vim to see a list of people who contributed. + * See README.txt for an overview of the Vim source code. + */ + +/* + * map.c: functions for maps and abbreviations + */ + +#include "vim.h" + +/* + * List used for abbreviations. + */ +static mapblock_T *first_abbr = NULL; // first entry in abbrlist + +/* + * Each mapping is put in one of the 256 hash lists, to speed up finding it. + */ +static mapblock_T *(maphash[256]); +static int maphash_valid = FALSE; + +/* + * Make a hash value for a mapping. + * "mode" is the lower 4 bits of the State for the mapping. + * "c1" is the first character of the "lhs". + * Returns a value between 0 and 255, index in maphash. + * Put Normal/Visual mode mappings mostly separately from Insert/Cmdline mode. + */ +#define MAP_HASH(mode, c1) (((mode) & (NORMAL + VISUAL + SELECTMODE + OP_PENDING + TERMINAL)) ? (c1) : ((c1) ^ 0x80)) + +/* + * Get the start of the hashed map list for "state" and first character "c". + */ + mapblock_T * +get_maphash_list(int state, int c) +{ + return maphash[MAP_HASH(state, c)]; +} + +/* + * Get the buffer-local hashed map list for "state" and first character "c". + */ + mapblock_T * +get_buf_maphash_list(int state, int c) +{ + return curbuf->b_maphash[MAP_HASH(state, c)]; +} + + int +is_maphash_valid(void) +{ + return maphash_valid; +} + +/* + * Initialize maphash[] for first use. + */ + static void +validate_maphash(void) +{ + if (!maphash_valid) + { + CLEAR_FIELD(maphash); + maphash_valid = TRUE; + } +} + +/* + * Delete one entry from the abbrlist or maphash[]. + * "mpp" is a pointer to the m_next field of the PREVIOUS entry! + */ + static void +map_free(mapblock_T **mpp) +{ + mapblock_T *mp; + + mp = *mpp; + vim_free(mp->m_keys); + vim_free(mp->m_str); + vim_free(mp->m_orig_str); + *mpp = mp->m_next; + vim_free(mp); +} + +/* + * Return characters to represent the map mode in an allocated string. + * Returns NULL when out of memory. + */ + static char_u * +map_mode_to_chars(int mode) +{ + garray_T mapmode; + + ga_init2(&mapmode, 1, 7); + + if ((mode & (INSERT + CMDLINE)) == INSERT + CMDLINE) + ga_append(&mapmode, '!'); // :map! + else if (mode & INSERT) + ga_append(&mapmode, 'i'); // :imap + else if (mode & LANGMAP) + ga_append(&mapmode, 'l'); // :lmap + else if (mode & CMDLINE) + ga_append(&mapmode, 'c'); // :cmap + else if ((mode & (NORMAL + VISUAL + SELECTMODE + OP_PENDING)) + == NORMAL + VISUAL + SELECTMODE + OP_PENDING) + ga_append(&mapmode, ' '); // :map + else + { + if (mode & NORMAL) + ga_append(&mapmode, 'n'); // :nmap + if (mode & OP_PENDING) + ga_append(&mapmode, 'o'); // :omap + if (mode & TERMINAL) + ga_append(&mapmode, 't'); // :tmap + if ((mode & (VISUAL + SELECTMODE)) == VISUAL + SELECTMODE) + ga_append(&mapmode, 'v'); // :vmap + else + { + if (mode & VISUAL) + ga_append(&mapmode, 'x'); // :xmap + if (mode & SELECTMODE) + ga_append(&mapmode, 's'); // :smap + } + } + + ga_append(&mapmode, NUL); + return (char_u *)mapmode.ga_data; +} + + static void +showmap( + mapblock_T *mp, + int local) // TRUE for buffer-local map +{ + int len = 1; + char_u *mapchars; + + if (message_filtered(mp->m_keys) && message_filtered(mp->m_str)) + return; + + if (msg_didout || msg_silent != 0) + { + msg_putchar('\n'); + if (got_int) // 'q' typed at MORE prompt + return; + } + + mapchars = map_mode_to_chars(mp->m_mode); + if (mapchars != NULL) + { + msg_puts((char *)mapchars); + len = (int)STRLEN(mapchars); + vim_free(mapchars); + } + + while (++len <= 3) + msg_putchar(' '); + + // Display the LHS. Get length of what we write. + len = msg_outtrans_special(mp->m_keys, TRUE, 0); + do + { + msg_putchar(' '); // padd with blanks + ++len; + } while (len < 12); + + if (mp->m_noremap == REMAP_NONE) + msg_puts_attr("*", HL_ATTR(HLF_8)); + else if (mp->m_noremap == REMAP_SCRIPT) + msg_puts_attr("&", HL_ATTR(HLF_8)); + else + msg_putchar(' '); + + if (local) + msg_putchar('@'); + else + msg_putchar(' '); + + // Use FALSE below if we only want things like to show up as such on + // the rhs, and not M-x etc, TRUE gets both -- webb + if (*mp->m_str == NUL) + msg_puts_attr("", HL_ATTR(HLF_8)); + else + { + // Remove escaping of CSI, because "m_str" is in a format to be used + // as typeahead. + char_u *s = vim_strsave(mp->m_str); + if (s != NULL) + { + vim_unescape_csi(s); + msg_outtrans_special(s, FALSE, 0); + vim_free(s); + } + } +#ifdef FEAT_EVAL + if (p_verbose > 0) + last_set_msg(mp->m_script_ctx); +#endif + out_flush(); // show one line at a time +} + + static int +map_add( + mapblock_T **map_table, + mapblock_T **abbr_table, + char_u *keys, + char_u *rhs, + char_u *orig_rhs, + int noremap, + int nowait, + int silent, + int mode, + int is_abbr, +#ifdef FEAT_EVAL + int expr, + scid_T sid, // -1 to use current_sctx + linenr_T lnum, +#endif + int simplified) +{ + mapblock_T *mp = ALLOC_ONE(mapblock_T); + + if (mp == NULL) + return FAIL; + + // If CTRL-C has been mapped, don't always use it for Interrupting. + if (*keys == Ctrl_C) + { + if (map_table == curbuf->b_maphash) + curbuf->b_mapped_ctrl_c |= mode; + else + mapped_ctrl_c |= mode; + } + + mp->m_keys = vim_strsave(keys); + mp->m_str = vim_strsave(rhs); + mp->m_orig_str = vim_strsave(orig_rhs); + if (mp->m_keys == NULL || mp->m_str == NULL) + { + vim_free(mp->m_keys); + vim_free(mp->m_str); + vim_free(mp->m_orig_str); + vim_free(mp); + return FAIL; + } + mp->m_keylen = (int)STRLEN(mp->m_keys); + mp->m_noremap = noremap; + mp->m_nowait = nowait; + mp->m_silent = silent; + mp->m_mode = mode; + mp->m_simplified = simplified; +#ifdef FEAT_EVAL + mp->m_expr = expr; + if (sid >= 0) + { + mp->m_script_ctx.sc_sid = sid; + mp->m_script_ctx.sc_lnum = lnum; + } + else + { + mp->m_script_ctx = current_sctx; + mp->m_script_ctx.sc_lnum += SOURCING_LNUM; + } +#endif + + // add the new entry in front of the abbrlist or maphash[] list + if (is_abbr) + { + mp->m_next = *abbr_table; + *abbr_table = mp; + } + else + { + int n = MAP_HASH(mp->m_mode, mp->m_keys[0]); + + mp->m_next = map_table[n]; + map_table[n] = mp; + } + return OK; +} + +/* + * map[!] : show all key mappings + * map[!] {lhs} : show key mapping for {lhs} + * map[!] {lhs} {rhs} : set key mapping for {lhs} to {rhs} + * noremap[!] {lhs} {rhs} : same, but no remapping for {rhs} + * unmap[!] {lhs} : remove key mapping for {lhs} + * abbr : show all abbreviations + * abbr {lhs} : show abbreviations for {lhs} + * abbr {lhs} {rhs} : set abbreviation for {lhs} to {rhs} + * noreabbr {lhs} {rhs} : same, but no remapping for {rhs} + * unabbr {lhs} : remove abbreviation for {lhs} + * + * maptype: 0 for :map, 1 for :unmap, 2 for noremap. + * + * arg is pointer to any arguments. Note: arg cannot be a read-only string, + * it will be modified. + * + * for :map mode is NORMAL + VISUAL + SELECTMODE + OP_PENDING + * for :map! mode is INSERT + CMDLINE + * for :cmap mode is CMDLINE + * for :imap mode is INSERT + * for :lmap mode is LANGMAP + * for :nmap mode is NORMAL + * for :vmap mode is VISUAL + SELECTMODE + * for :xmap mode is VISUAL + * for :smap mode is SELECTMODE + * for :omap mode is OP_PENDING + * for :tmap mode is TERMINAL + * + * for :abbr mode is INSERT + CMDLINE + * for :iabbr mode is INSERT + * for :cabbr mode is CMDLINE + * + * Return 0 for success + * 1 for invalid arguments + * 2 for no match + * 4 for out of mem + * 5 for entry not unique + */ + int +do_map( + int maptype, + char_u *arg, + int mode, + int abbrev) // not a mapping but an abbreviation +{ + char_u *keys; + mapblock_T *mp, **mpp; + char_u *rhs; + char_u *p; + int n; + int len = 0; // init for GCC + int hasarg; + int haskey; + int do_print; + int keyround; + char_u *keys_buf = NULL; + char_u *alt_keys_buf = NULL; + char_u *arg_buf = NULL; + int retval = 0; + int do_backslash; + mapblock_T **abbr_table; + mapblock_T **map_table; + int unique = FALSE; + int nowait = FALSE; + int silent = FALSE; + int special = FALSE; +#ifdef FEAT_EVAL + int expr = FALSE; +#endif + int did_simplify = FALSE; + int noremap; + char_u *orig_rhs; + + keys = arg; + map_table = maphash; + abbr_table = &first_abbr; + + // For ":noremap" don't remap, otherwise do remap. + if (maptype == 2) + noremap = REMAP_NONE; + else + noremap = REMAP_YES; + + // Accept , , ,