/// Add the digraphs in the argument to the digraph table. /// format: {c1}{c2} char {c1}{c2} char ... /// /// @param str void putdigraph(char_u *str) { char_u char1, char2; digr_T *dp; while (*str != NUL) { str = skipwhite(str); if (*str == NUL) { return; } char1 = *str++; char2 = *str++; if (char2 == 0) { EMSG(_(e_invarg)); return; } if ((char1 == ESC) || (char2 == ESC)) { EMSG(_("E104: Escape not allowed in digraph")); return; } str = skipwhite(str); if (!ascii_isdigit(*str)) { EMSG(_(e_number_exp)); return; } int n = getdigits_int(&str); // If the digraph already exists, replace the result. dp = (digr_T *)user_digraphs.ga_data; int i; for (i = 0; i < user_digraphs.ga_len; ++i) { if (((int)dp->char1 == char1) && ((int)dp->char2 == char2)) { dp->result = n; break; } ++dp; } // Add a new digraph to the table. if (i == user_digraphs.ga_len) { dp = GA_APPEND_VIA_PTR(digr_T, &user_digraphs); dp->char1 = char1; dp->char2 = char2; dp->result = n; } } }
/// Helper for init_chartab /// /// @param global false: only set buf->b_chartab[] /// /// @return FAIL if 'iskeyword', 'isident', 'isfname' or 'isprint' option has /// an error, OK otherwise. int buf_init_chartab(buf_T *buf, int global) { int c; int c2; int i; bool tilde; bool do_isalpha; if (global) { // Set the default size for printable characters: // From <Space> to '~' is 1 (printable), others are 2 (not printable). // This also inits all 'isident' and 'isfname' flags to false. c = 0; while (c < ' ') { g_chartab[c++] = (dy_flags & DY_UHEX) ? 4 : 2; } while (c <= '~') { g_chartab[c++] = 1 + CT_PRINT_CHAR; } if (p_altkeymap) { while (c < YE) { g_chartab[c++] = 1 + CT_PRINT_CHAR; } } while (c < 256) { if (c >= 0xa0) { // UTF-8: bytes 0xa0 - 0xff are printable (latin1) g_chartab[c++] = CT_PRINT_CHAR + 1; } else { // the rest is unprintable by default g_chartab[c++] = (dy_flags & DY_UHEX) ? 4 : 2; } } // Assume that every multi-byte char is a filename character. for (c = 1; c < 256; c++) { if (c >= 0xa0) { g_chartab[c] |= CT_FNAME_CHAR; } } } // Init word char flags all to false memset(buf->b_chartab, 0, (size_t)32); // In lisp mode the '-' character is included in keywords. if (buf->b_p_lisp) { SET_CHARTAB(buf, '-'); } // Walk through the 'isident', 'iskeyword', 'isfname' and 'isprint' // options Each option is a list of characters, character numbers or // ranges, separated by commas, e.g.: "200-210,x,#-178,-" for (i = global ? 0 : 3; i <= 3; i++) { const char_u *p; if (i == 0) { // first round: 'isident' p = p_isi; } else if (i == 1) { // second round: 'isprint' p = p_isp; } else if (i == 2) { // third round: 'isfname' p = p_isf; } else { // i == 3 // fourth round: 'iskeyword' p = buf->b_p_isk; } while (*p) { tilde = false; do_isalpha = false; if ((*p == '^') && (p[1] != NUL)) { tilde = true; ++p; } if (ascii_isdigit(*p)) { c = getdigits_int((char_u **)&p); } else { c = mb_ptr2char_adv(&p); } c2 = -1; if ((*p == '-') && (p[1] != NUL)) { ++p; if (ascii_isdigit(*p)) { c2 = getdigits_int((char_u **)&p); } else { c2 = mb_ptr2char_adv(&p); } } if ((c <= 0) || (c >= 256) || ((c2 < c) && (c2 != -1)) || (c2 >= 256) || !((*p == NUL) || (*p == ','))) { return FAIL; } if (c2 == -1) { // not a range // A single '@' (not "@-@"): // Decide on letters being ID/printable/keyword chars with // standard function isalpha(). This takes care of locale for // single-byte characters). if (c == '@') { do_isalpha = true; c = 1; c2 = 255; } else { c2 = c; } } while (c <= c2) { // Use the MB_ functions here, because isalpha() doesn't // work properly when 'encoding' is "latin1" and the locale is // "C". if (!do_isalpha || mb_islower(c) || mb_isupper(c) || (p_altkeymap && (F_isalpha(c) || F_isdigit(c)))) { if (i == 0) { // (re)set ID flag if (tilde) { g_chartab[c] &= (uint8_t)~CT_ID_CHAR; } else { g_chartab[c] |= CT_ID_CHAR; } } else if (i == 1) { // (re)set printable // For double-byte we keep the cell width, so // that we can detect it from the first byte. if (((c < ' ') || (c > '~') || (p_altkeymap && (F_isalpha(c) || F_isdigit(c))))) { if (tilde) { g_chartab[c] = (uint8_t)((g_chartab[c] & ~CT_CELL_MASK) + ((dy_flags & DY_UHEX) ? 4 : 2)); g_chartab[c] &= (uint8_t)~CT_PRINT_CHAR; } else { g_chartab[c] = (uint8_t)((g_chartab[c] & ~CT_CELL_MASK) + 1); g_chartab[c] |= CT_PRINT_CHAR; } } } else if (i == 2) { // (re)set fname flag if (tilde) { g_chartab[c] &= (uint8_t)~CT_FNAME_CHAR; } else { g_chartab[c] |= CT_FNAME_CHAR; } } else { // i == 3 // (re)set keyword flag if (tilde) { RESET_CHARTAB(buf, c); } else { SET_CHARTAB(buf, c); } } } ++c; } c = *p; p = skip_to_option_part(p); if ((c == ',') && (*p == NUL)) { // Trailing comma is not allowed. return FAIL; } } } chartab_initialized = true; return OK; }
/* * 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: ; }
/* * Parse the 'guicursor' option ("what" is SHAPE_CURSOR) or 'mouseshape' * ("what" is SHAPE_MOUSE). * Returns error message for an illegal option, NULL otherwise. */ char_u *parse_shape_opt(int what) { char_u *modep; char_u *colonp; char_u *commap; char_u *slashp; char_u *p, *endp; int idx = 0; /* init for GCC */ int all_idx; int len; int i; int found_ve = FALSE; /* found "ve" flag */ int round; /* * First round: check for errors; second round: do it for real. */ for (round = 1; round <= 2; ++round) { /* * Repeat for all comma separated parts. */ modep = p_guicursor; while (*modep != NUL) { colonp = vim_strchr(modep, ':'); if (colonp == NULL) return (char_u *)N_("E545: Missing colon"); if (colonp == modep) return (char_u *)N_("E546: Illegal mode"); commap = vim_strchr(modep, ','); /* * Repeat for all mode's before the colon. * For the 'a' mode, we loop to handle all the modes. */ all_idx = -1; assert(modep < colonp); while (modep < colonp || all_idx >= 0) { if (all_idx < 0) { /* Find the mode. */ if (modep[1] == '-' || modep[1] == ':') len = 1; else len = 2; if (len == 1 && TOLOWER_ASC(modep[0]) == 'a') all_idx = SHAPE_IDX_COUNT - 1; else { for (idx = 0; idx < SHAPE_IDX_COUNT; ++idx) if (STRNICMP(modep, shape_table[idx].name, len) == 0) break; if (idx == SHAPE_IDX_COUNT || (shape_table[idx].used_for & what) == 0) return (char_u *)N_("E546: Illegal mode"); if (len == 2 && modep[0] == 'v' && modep[1] == 'e') found_ve = TRUE; } modep += len + 1; } if (all_idx >= 0) idx = all_idx--; else if (round == 2) { { /* Set the defaults, for the missing parts */ shape_table[idx].shape = SHAPE_BLOCK; shape_table[idx].blinkwait = 700L; shape_table[idx].blinkon = 400L; shape_table[idx].blinkoff = 250L; } } /* Parse the part after the colon */ for (p = colonp + 1; *p && *p != ','; ) { { /* * First handle the ones with a number argument. */ i = *p; len = 0; if (STRNICMP(p, "ver", 3) == 0) len = 3; else if (STRNICMP(p, "hor", 3) == 0) len = 3; else if (STRNICMP(p, "blinkwait", 9) == 0) len = 9; else if (STRNICMP(p, "blinkon", 7) == 0) len = 7; else if (STRNICMP(p, "blinkoff", 8) == 0) len = 8; if (len != 0) { p += len; if (!ascii_isdigit(*p)) return (char_u *)N_("E548: digit expected"); int n = getdigits_int(&p); if (len == 3) { /* "ver" or "hor" */ if (n == 0) return (char_u *)N_("E549: Illegal percentage"); if (round == 2) { if (TOLOWER_ASC(i) == 'v') shape_table[idx].shape = SHAPE_VER; else shape_table[idx].shape = SHAPE_HOR; shape_table[idx].percentage = n; } } else if (round == 2) { if (len == 9) shape_table[idx].blinkwait = n; else if (len == 7) shape_table[idx].blinkon = n; else shape_table[idx].blinkoff = n; } } else if (STRNICMP(p, "block", 5) == 0) { if (round == 2) shape_table[idx].shape = SHAPE_BLOCK; p += 5; } else { /* must be a highlight group name then */ endp = vim_strchr(p, '-'); if (commap == NULL) { /* last part */ if (endp == NULL) endp = p + STRLEN(p); /* find end of part */ } else if (endp > commap || endp == NULL) endp = commap; slashp = vim_strchr(p, '/'); if (slashp != NULL && slashp < endp) { /* "group/langmap_group" */ i = syn_check_group(p, (int)(slashp - p)); p = slashp + 1; } if (round == 2) { shape_table[idx].id = syn_check_group(p, (int)(endp - p)); shape_table[idx].id_lm = shape_table[idx].id; if (slashp != NULL && slashp < endp) shape_table[idx].id = i; } p = endp; } } /* if (what != SHAPE_MOUSE) */ if (*p == '-') ++p; } } modep = p; if (*modep == ',') ++modep; } } /* If the 's' flag is not given, use the 'v' cursor for 's' */ if (!found_ve) { { shape_table[SHAPE_IDX_VE].shape = shape_table[SHAPE_IDX_V].shape; shape_table[SHAPE_IDX_VE].percentage = shape_table[SHAPE_IDX_V].percentage; shape_table[SHAPE_IDX_VE].blinkwait = shape_table[SHAPE_IDX_V].blinkwait; shape_table[SHAPE_IDX_VE].blinkon = shape_table[SHAPE_IDX_V].blinkon; shape_table[SHAPE_IDX_VE].blinkoff = shape_table[SHAPE_IDX_V].blinkoff; shape_table[SHAPE_IDX_VE].id = shape_table[SHAPE_IDX_V].id; shape_table[SHAPE_IDX_VE].id_lm = shape_table[SHAPE_IDX_V].id_lm; } } return NULL; }