📄 getchar.c
字号:
map_free(mpp);
continue; /* continue with *mpp */
}
/*
* May need to put this entry into another hash list.
*/
new_hash = MAP_HASH(mp->m_mode, mp->m_keys[0]);
if (!abbrev && new_hash != hash)
{
*mpp = mp->m_next;
mp->m_next = maphash[new_hash];
maphash[new_hash] = mp;
continue; /* continue with *mpp */
}
}
}
mpp = &(mp->m_next);
}
}
}
if (maptype == 1) /* delete entry */
{
if (!did_it)
retval = 2; /* no match */
goto theend;
}
if (!haskey || !hasarg) /* print entries */
{
if (!did_it)
{
if (abbrev)
MSG("No abbreviation found");
else
MSG("No mapping found");
}
goto theend; /* listing finished */
}
if (did_it) /* have added the new entry already */
goto theend;
/*
* Get here when we have to add a new entry to the maphash[] list or abbrlist.
*/
mp = (struct mapblock *)alloc((unsigned)sizeof(struct mapblock));
if (mp == NULL)
{
retval = 4; /* no mem */
goto theend;
}
#ifdef USE_GUI_WIN32
/* If CTRL-C has been mapped, don't use it for Interrupting */
if (*keys == Ctrl('C'))
mapped_ctrl_c = TRUE;
#endif
mp->m_keys = vim_strsave(keys);
mp->m_str = vim_strsave(arg);
if (mp->m_keys == NULL || mp->m_str == NULL)
{
vim_free(mp->m_keys);
vim_free(mp->m_str);
vim_free(mp);
retval = 4; /* no mem */
goto theend;
}
mp->m_keylen = STRLEN(mp->m_keys);
mp->m_noremap = maptype;
mp->m_mode = mode;
/* add the new entry in front of the abbrlist or maphash[] list */
if (abbrev)
{
mp->m_next = first_abbr;
first_abbr = mp;
}
else
{
n = MAP_HASH(mp->m_mode, mp->m_keys[0]);
mp->m_next = maphash[n];
maphash[n] = mp;
}
theend:
vim_free(keys_buf);
vim_free(arg_buf);
return retval;
}
/*
* 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(mpp)
struct mapblock **mpp;
{
struct mapblock *mp;
mp = *mpp;
vim_free(mp->m_keys);
vim_free(mp->m_str);
*mpp = mp->m_next;
vim_free(mp);
}
/*
* Initialize maphash[] for first use.
*/
static void
validate_maphash()
{
if (!maphash_valid)
{
vim_memset(maphash, 0, sizeof(maphash));
maphash_valid = TRUE;
}
}
/*
* Get the mapping mode from the command name.
*/
int
get_map_mode(cmdp, forceit)
char_u **cmdp;
int forceit;
{
char_u *p;
int modec;
int mode;
p = *cmdp;
modec = *p++;
if (modec == 'i')
mode = INSERT; /* :imap */
else if (modec == 'c')
mode = CMDLINE; /* :cmap */
else if (modec == 'n' && *p != 'o') /* avoid :noremap */
mode = NORMAL; /* :nmap */
else if (modec == 'v')
mode = VISUAL; /* :vmap */
else if (modec == 'o')
mode = OP_PENDING; /* :omap */
else
{
--p;
if (forceit)
mode = INSERT + CMDLINE; /* :map ! */
else
mode = VISUAL + NORMAL + OP_PENDING;/* :map */
}
*cmdp = p;
return mode;
}
/*
* Clear all mappings or abbreviations.
* 'abbr' should be FALSE for mappings, TRUE for abbreviations.
*/
void
map_clear(cmdp, forceit, abbr)
char_u *cmdp;
int forceit;
int abbr;
{
struct mapblock *mp, **mpp;
int mode;
int hash;
int new_hash;
validate_maphash();
mode = get_map_mode(&cmdp, forceit);
for (hash = 0; hash < 256; ++hash)
{
if (abbr)
{
if (hash) /* there is only one abbrlist */
break;
mpp = &first_abbr;
}
else
mpp = &maphash[hash];
while (*mpp != NULL)
{
mp = *mpp;
if (mp->m_mode & mode)
{
mp->m_mode &= ~mode;
if (mp->m_mode == 0) /* entry can be deleted */
{
map_free(mpp);
continue;
}
/*
* May need to put this entry into another hash list.
*/
new_hash = MAP_HASH(mp->m_mode, mp->m_keys[0]);
if (!abbr && new_hash != hash)
{
*mpp = mp->m_next;
mp->m_next = maphash[new_hash];
maphash[new_hash] = mp;
continue; /* continue with *mpp */
}
}
mpp = &(mp->m_next);
}
}
}
static void
showmap(mp)
struct mapblock *mp;
{
int len = 1;
if (msg_didout)
msg_putchar('\n');
if ((mp->m_mode & (INSERT + CMDLINE)) == INSERT + CMDLINE)
msg_putchar('!'); /* :map! */
else if (mp->m_mode & INSERT)
msg_putchar('i'); /* :imap */
else if (mp->m_mode & CMDLINE)
msg_putchar('c'); /* :cmap */
else if ((mp->m_mode & (NORMAL + VISUAL + OP_PENDING))
== NORMAL + VISUAL + OP_PENDING)
msg_putchar(' '); /* :map */
else
{
len = 0;
if (mp->m_mode & NORMAL)
{
msg_putchar('n'); /* :nmap */
++len;
}
if (mp->m_mode & OP_PENDING)
{
msg_putchar('o'); /* :omap */
++len;
}
if (mp->m_mode & VISUAL)
{
msg_putchar('v'); /* :vmap */
++len;
}
}
while (++len <= 3)
msg_putchar(' ');
/* Get length of what we write */
len = msg_outtrans_special(mp->m_keys, TRUE);
do
{
msg_putchar(' '); /* padd with blanks */
++len;
} while (len < 12);
if (mp->m_noremap)
msg_puts_attr((char_u *)"*", hl_attr(HLF_8));
else
msg_putchar(' ');
/* Use FALSE below if we only want things like <Up> 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((char_u *)"<Nop>", hl_attr(HLF_8));
else
msg_outtrans_special(mp->m_str, TRUE);
out_flush(); /* show one line at a time */
}
/*
* Check for an abbreviation.
* Cursor is at ptr[col]. When inserting, mincol is where insert started.
* "c" is the character typed before check_abbr was called.
*
* Historic vi practice: The last character of an abbreviation must be an id
* character ([a-zA-Z0-9_]). The characters in front of it must be all id
* characters or all non-id characters. This allows for abbr. "#i" to
* "#include".
*
* Vim addition: Allow for abbreviations that end in a non-keyword character.
* Then there must be white space before the abbr.
*
* return TRUE if there is an abbreviation, FALSE if not
*/
int
check_abbr(c, ptr, col, mincol)
int c;
char_u *ptr;
int col;
int mincol;
{
int len;
int j;
char_u tb[4];
struct mapblock *mp;
int is_id = TRUE;
int vim_abbr;
if (no_abbr_cnt) /* abbrev. are not recursive */
return FALSE;
/*
* Check for word before the cursor: If it ends in a keyword char all
* chars before it must be al keyword chars or non-keyword chars, but not
* white space. If it ends in a non-keyword char we accept any characters
* before it except white space.
*/
if (col == 0) /* cannot be an abbr. */
return FALSE;
if (!vim_iswordc(ptr[col - 1]))
vim_abbr = TRUE; /* Vim added abbr. */
else
{
vim_abbr = FALSE; /* vi compatible abbr. */
if (col > 1)
is_id = vim_iswordc(ptr[col - 2]);
}
for (len = col - 1; len > 0 && !vim_isspace(ptr[len - 1]) &&
(vim_abbr || is_id == vim_iswordc(ptr[len - 1])); --len)
;
if (len < mincol)
len = mincol;
if (len < col) /* there is a word in front of the cursor */
{
ptr += len;
len = col - len;
for (mp = first_abbr; mp; mp = mp->m_next)
{
/* find entries with right mode and keys */
if ( (mp->m_mode & State)
&& mp->m_keylen == len
&& !STRNCMP(mp->m_keys, ptr, (size_t)len))
break;
}
if (mp)
{
/*
* Found a match:
* Insert the rest of the abbreviation in typebuf[].
* This goes from end to start.
*
* Characters 0x000 - 0x100: normal chars, may need CTRL-V,
* except K_SPECIAL: Becomes K_SPECIAL KS_SPECIAL K_FILLER
* Characters where IS_SPECIAL() == TRUE: key codes, need
* K_SPECIAL. Other characters (with ABBR_OFF): don't use CTRL-V.
*
* Character CTRL(']') is treated specially - it completes the
* abbreviation, but is not inserted into the input stream.
*/
j = 0;
/* special key code, split up */
if (c != Ctrl(']'))
{
if (IS_SPECIAL(c) || c == K_SPECIAL)
{
tb[j++] = K_SPECIAL;
tb[j++] = K_SECOND(c);
c = K_THIRD(c);
}
else if (c < 0x100 && (c < ' ' || c > '~'))
tb[j++] = Ctrl('V'); /* special char needs CTRL-V */
tb[j++] = c;
tb[j] = NUL;
/* insert the last typed char */
(void)ins_typebuf(tb, TRUE, 0, TRUE);
}
/* insert the to string */
(void)ins_typebuf(mp->m_str, mp->m_noremap ? -1 : 0, 0, TRUE);
/* no abbrev. for these chars */
no_abbr_cnt += STRLEN(mp->m_str) + j + 1;
tb[0] = Ctrl('H');
tb[1] = NUL;
while (len--) /* delete the from string */
(void)ins_typebuf(tb, TRUE, 0, TRUE);
return TRUE;
}
}
return FALSE;
}
/*
* Write map commands for the current mappings to an .exrc file.
* Return FAIL on error, OK otherwise.
*/
int
makemap(fd)
FILE *fd;
{
struct mapblock *mp;
char_u c1, c2;
char_u *p;
char *cmd;
int abbr;
int hash;
int did_cpo = FALSE;
int i;
validate_maphash();
/*
* Do the loop twice: Once for mappings, once for abbreviations.
* Then loop over all map hash lists.
*/
for (abbr = 0; abbr < 2; ++abbr)
for (hash = 0; hash < 256; ++hash)
{
if (abbr)
{
if (hash) /* there is only one abbr list */
break;
mp = first_abbr;
}
else
mp = maphash[hash];
for ( ; mp; mp = mp->m_next)
{
c1 = NUL;
c2 = NUL;
if (abbr)
cmd = "abbr";
else
cmd = "map";
switch (mp->m_mode)
{
case NORMAL + VISUAL + OP_PENDING:
break;
case NORMAL:
c1 = 'n';
break;
case VISUAL:
c1 = 'v';
break;
case OP_PENDING:
c1 = 'o';
break;
case NORMAL + VISUAL:
c1 = 'n';
c2 = 'v';
break;
case VISUAL + OP_PENDING:
c1 = 'v';
c2 = 'o';
break;
case NORMAL + OP_PENDING:
c1 = 'n';
c2 = 'o';
break;
case CMDLINE + INSERT:
if (!abbr)
cmd = "map!";
break;
case CMDLINE:
c1 = 'c';
break;
case INSERT:
c1 = 'i';
break;
default:
EMSG("makemap: Illegal mode");
return FAIL;
}
do /* may do this twice if c2 is set */
{
/* When outputting <> form, need to make sure that 'cpo'
* is empty. */
if (!did_cpo)
{
if (*mp->m_str == NUL) /* will use <Nop> */
did_cpo = TRUE;
else
for (i = 0; i < 2; ++i)
for (p = (i ? mp->m_str : mp->m_keys); *p; ++p)
if (*p == K_SPECIAL || *p == NL)
did_cpo = TRUE;
if (did_cpo)
{
if (fprintf(fd,
#ifdef USE_CRNL
"let cpo_save=&cpo\r\nset cpo=\r\n"
#else
"let cpo_save=&cpo\nset cpo=\n"
#endif
) < 0)
return FAIL;
}
}
if (c1 && putc(c1, fd) < 0)
return FAIL;
if (mp->m_noremap && fprintf(fd, "nore") < 0)
return FAIL;
if (fprintf(fd, cmd) < 0)
return FAIL;
if ( putc(' ', fd) < 0
|| putescstr(fd, mp->m_keys, FALSE) == FAIL
|| putc(' ', fd) < 0
|| putescstr(fd, mp->m_str, FALSE) == FAIL
#ifdef USE_CRNL
|| putc('\r', fd) < 0
#endif
|| putc('\n', fd) < 0)
return FAIL;
c1 = c2;
c2 = NUL;
}
while (c1);
}
}
if (did_cpo)
if (fprintf(fd,
#ifdef USE_CRNL
"let &cpo=cpo_save\r\nunlet cpo_save\r\n"
#else
"let &cpo=cpo_save\nunlet cpo_save\n"
#endif
) < 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -