comparison src/highlight.c @ 26057:92c424550367 v8.2.3562

patch 8.2.3562: cannot add color names Commit: https://github.com/vim/vim/commit/e30d10253fa634c4f60daa798d029245f4eed393 Author: Drew Vogel <dvogel@github> Date: Sun Oct 24 20:35:07 2021 +0100 patch 8.2.3562: cannot add color names Problem: Cannot add color names. Solution: Add the v:colornames dictionary. (Drew Vogel, closes https://github.com/vim/vim/issues/8761)
author Bram Moolenaar <Bram@vim.org>
date Sun, 24 Oct 2021 21:45:04 +0200
parents 09a273f0af05
children c7e09c069ece
comparison
equal deleted inserted replaced
26056:977bbbf36908 26057:92c424550367
473 473
474 recursive = TRUE; 474 recursive = TRUE;
475 buf = alloc(STRLEN(name) + 12); 475 buf = alloc(STRLEN(name) + 12);
476 if (buf != NULL) 476 if (buf != NULL)
477 { 477 {
478 #ifdef FEAT_EVAL
479 load_default_colors_lists();
480 #endif
478 apply_autocmds(EVENT_COLORSCHEMEPRE, name, 481 apply_autocmds(EVENT_COLORSCHEMEPRE, name,
479 curbuf->b_fname, FALSE, curbuf); 482 curbuf->b_fname, FALSE, curbuf);
480 sprintf((char *)buf, "colors/%s.vim", name); 483 sprintf((char *)buf, "colors/%s.vim", name);
481 retval = source_runtime(buf, DIP_START + DIP_OPT); 484 retval = source_runtime(buf, DIP_START + DIP_OPT);
482 vim_free(buf); 485 vim_free(buf);
1188 { 1191 {
1189 if (!init) 1192 if (!init)
1190 HL_TABLE()[idx].sg_set |= SG_GUI; 1193 HL_TABLE()[idx].sg_set |= SG_GUI;
1191 1194
1192 # if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) 1195 # if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
1193 // In GUI guifg colors are only used when recognized 1196 // In GUI guibg colors are only used when recognized
1194 i = color_name2handle(arg); 1197 i = color_name2handle(arg);
1195 if (i != INVALCOLOR || STRCMP(arg, "NONE") == 0 || !USE_24BIT) 1198 if (i != INVALCOLOR || STRCMP(arg, "NONE") == 0 || !USE_24BIT)
1196 { 1199 {
1197 HL_TABLE()[idx].sg_gui_bg = i; 1200 HL_TABLE()[idx].sg_gui_bg = i;
1198 # endif 1201 # endif
2228 return GUI_GET_COLOR((char_u *)(*p_bg == 'l' ? "white" : "black")); 2231 return GUI_GET_COLOR((char_u *)(*p_bg == 'l' ? "white" : "black"));
2229 #endif 2232 #endif
2230 } 2233 }
2231 2234
2232 return GUI_GET_COLOR(name); 2235 return GUI_GET_COLOR(name);
2236 }
2237
2238 // On MS-Windows an RGB macro is available and it produces 0x00bbggrr color
2239 // values as used by the MS-Windows GDI api. It should be used only for
2240 // MS-Windows GDI builds.
2241 # if defined(RGB) && defined(MSWIN) && !defined(FEAT_GUI)
2242 # undef RGB
2243 # endif
2244 # ifndef RGB
2245 # define RGB(r, g, b) ((r<<16) | (g<<8) | (b))
2246 # endif
2247
2248 # ifdef VIMDLL
2249 static guicolor_T
2250 gui_adjust_rgb(guicolor_T c)
2251 {
2252 if (gui.in_use)
2253 return c;
2254 else
2255 return ((c & 0xff) << 16) | (c & 0x00ff00) | ((c >> 16) & 0xff);
2256 }
2257 # else
2258 # define gui_adjust_rgb(c) (c)
2259 # endif
2260
2261 static int
2262 hex_digit(int c)
2263 {
2264 if (isdigit(c))
2265 return c - '0';
2266 c = TOLOWER_ASC(c);
2267 if (c >= 'a' && c <= 'f')
2268 return c - 'a' + 10;
2269 return 0x1ffffff;
2270 }
2271
2272 guicolor_T
2273 decode_hex_color(char_u *hex)
2274 {
2275 guicolor_T color;
2276
2277 if (hex[0] != '#' || STRLEN(hex) != 7)
2278 return INVALCOLOR;
2279
2280 // Name is in "#rrggbb" format
2281 color = RGB(((hex_digit(hex[1]) << 4) + hex_digit(hex[2])),
2282 ((hex_digit(hex[3]) << 4) + hex_digit(hex[4])),
2283 ((hex_digit(hex[5]) << 4) + hex_digit(hex[6])));
2284 if (color > 0xffffff)
2285 return INVALCOLOR;
2286 return gui_adjust_rgb(color);
2287 }
2288
2289 #if defined(FEAT_EVAL)
2290 // Returns the color currently mapped to the given name or INVALCOLOR if no
2291 // such name exists in the color table. The convention is to use lowercase for
2292 // all keys in the v:colornames dictionary. The value can be either a string in
2293 // the form #rrggbb or a number, either of which is converted to a guicolor_T.
2294 guicolor_T
2295 colorname2rgb(char_u *name)
2296 {
2297 dict_T *colornames_table = get_vim_var_dict(VV_COLORNAMES);
2298 char_u *lc_name;
2299 dictitem_T *colentry;
2300 char_u *colstr;
2301 varnumber_T colnum;
2302
2303 lc_name = strlow_save(name);
2304 if (lc_name == NULL)
2305 return INVALCOLOR;
2306
2307 colentry = dict_find(colornames_table, lc_name, -1);
2308 vim_free(lc_name);
2309 if (colentry == NULL)
2310 return INVALCOLOR;
2311
2312 if (colentry->di_tv.v_type == VAR_STRING)
2313 {
2314 colstr = tv_get_string_strict(&colentry->di_tv);
2315 if ((STRLEN(colstr) == 7) && (*colstr == '#'))
2316 {
2317 return decode_hex_color(colstr);
2318 }
2319 else
2320 {
2321 semsg(_(e_bad_color_string_str), colstr);
2322 return INVALCOLOR;
2323 }
2324 }
2325
2326 if (colentry->di_tv.v_type == VAR_NUMBER)
2327 {
2328 colnum = tv_get_number(&colentry->di_tv);
2329 return (guicolor_T)colnum;
2330 }
2331
2332 return INVALCOLOR;
2333 }
2334
2335 // Maps the given name to the given color value, overwriting any current
2336 // mapping. If allocation fails the named color will no longer exist in the
2337 // table and the user will receive an error message.
2338 void
2339 save_colorname_hexstr(int r, int g, int b, char_u *name)
2340 {
2341 int result;
2342 dict_T *colornames_table;
2343 dictitem_T *existing;
2344 char_u hexstr[8];
2345
2346 if (vim_snprintf((char *)hexstr, sizeof(hexstr),
2347 "#%02x%02x%02x", r, g, b) < 0)
2348 {
2349 semsg(_(e_cannot_allocate_color_str), name);
2350 return;
2351 }
2352
2353 colornames_table = get_vim_var_dict(VV_COLORNAMES);
2354 // The colornames_table dict is safe to use here because it is allocated at
2355 // startup in evalvars.c
2356 existing = dict_find(colornames_table, name, -1);
2357 if (existing != NULL)
2358 {
2359 dictitem_remove(colornames_table, existing);
2360 existing = NULL; // dictitem_remove freed the item
2361 }
2362
2363 result = dict_add_string(colornames_table, (char *)name, hexstr);
2364 if (result == FAIL)
2365 semsg(_(e_cannot_allocate_color_str), name);
2366 }
2367
2368 /*
2369 * Load a default color list. Intended to support legacy color names but allows
2370 * the user to override the color values. Only loaded once.
2371 */
2372 void
2373 load_default_colors_lists()
2374 {
2375 // Lacking a default color list isn't the end of the world but it is likely
2376 // an inconvenience so users should know when it is missing.
2377 if (source_runtime((char_u *)"colors/lists/default.vim", DIP_ALL) != OK)
2378 msg("failed to load colors/lists/default.vim");
2379 }
2380 #endif
2381
2382 guicolor_T
2383 gui_get_color_cmn(char_u *name)
2384 {
2385 int i;
2386 guicolor_T color;
2387
2388 struct rgbcolor_table_S {
2389 char_u *color_name;
2390 guicolor_T color;
2391 };
2392
2393 // Only non X11 colors (not present in rgb.txt) and colors in
2394 // color_names[], useful when $VIMRUNTIME is not found,.
2395 static struct rgbcolor_table_S rgb_table[] = {
2396 {(char_u *)"black", RGB(0x00, 0x00, 0x00)},
2397 {(char_u *)"blue", RGB(0x00, 0x00, 0xFF)},
2398 {(char_u *)"brown", RGB(0xA5, 0x2A, 0x2A)},
2399 {(char_u *)"cyan", RGB(0x00, 0xFF, 0xFF)},
2400 {(char_u *)"darkblue", RGB(0x00, 0x00, 0x8B)},
2401 {(char_u *)"darkcyan", RGB(0x00, 0x8B, 0x8B)},
2402 {(char_u *)"darkgray", RGB(0xA9, 0xA9, 0xA9)},
2403 {(char_u *)"darkgreen", RGB(0x00, 0x64, 0x00)},
2404 {(char_u *)"darkgrey", RGB(0xA9, 0xA9, 0xA9)},
2405 {(char_u *)"darkmagenta", RGB(0x8B, 0x00, 0x8B)},
2406 {(char_u *)"darkred", RGB(0x8B, 0x00, 0x00)},
2407 {(char_u *)"darkyellow", RGB(0x8B, 0x8B, 0x00)}, // No X11
2408 {(char_u *)"gray", RGB(0xBE, 0xBE, 0xBE)},
2409 {(char_u *)"green", RGB(0x00, 0xFF, 0x00)},
2410 {(char_u *)"grey", RGB(0xBE, 0xBE, 0xBE)},
2411 {(char_u *)"grey40", RGB(0x66, 0x66, 0x66)},
2412 {(char_u *)"grey50", RGB(0x7F, 0x7F, 0x7F)},
2413 {(char_u *)"grey90", RGB(0xE5, 0xE5, 0xE5)},
2414 {(char_u *)"lightblue", RGB(0xAD, 0xD8, 0xE6)},
2415 {(char_u *)"lightcyan", RGB(0xE0, 0xFF, 0xFF)},
2416 {(char_u *)"lightgray", RGB(0xD3, 0xD3, 0xD3)},
2417 {(char_u *)"lightgreen", RGB(0x90, 0xEE, 0x90)},
2418 {(char_u *)"lightgrey", RGB(0xD3, 0xD3, 0xD3)},
2419 {(char_u *)"lightmagenta", RGB(0xFF, 0x8B, 0xFF)}, // No X11
2420 {(char_u *)"lightred", RGB(0xFF, 0x8B, 0x8B)}, // No X11
2421 {(char_u *)"lightyellow", RGB(0xFF, 0xFF, 0xE0)},
2422 {(char_u *)"magenta", RGB(0xFF, 0x00, 0xFF)},
2423 {(char_u *)"red", RGB(0xFF, 0x00, 0x00)},
2424 {(char_u *)"seagreen", RGB(0x2E, 0x8B, 0x57)},
2425 {(char_u *)"white", RGB(0xFF, 0xFF, 0xFF)},
2426 {(char_u *)"yellow", RGB(0xFF, 0xFF, 0x00)},
2427 };
2428
2429 color = decode_hex_color(name);
2430 if (color != INVALCOLOR)
2431 return color;
2432
2433 // Check if the name is one of the colors we know
2434 for (i = 0; i < (int)ARRAY_LENGTH(rgb_table); i++)
2435 if (STRICMP(name, rgb_table[i].color_name) == 0)
2436 return gui_adjust_rgb(rgb_table[i].color);
2437
2438 #if defined(FEAT_EVAL)
2439 /*
2440 * Not a traditional color. Load additional color aliases and then consult the alias table.
2441 */
2442
2443 color = colorname2rgb(name);
2444 if (color == INVALCOLOR)
2445 {
2446 load_default_colors_lists();
2447 color = colorname2rgb(name);
2448 }
2449
2450 return color;
2451 #else
2452 return INVALCOLOR;
2453 #endif
2454 }
2455
2456 guicolor_T
2457 gui_get_rgb_color_cmn(int r, int g, int b)
2458 {
2459 guicolor_T color = RGB(r, g, b);
2460
2461 if (color > 0xffffff)
2462 return INVALCOLOR;
2463 return gui_adjust_rgb(color);
2233 } 2464 }
2234 #endif 2465 #endif
2235 2466
2236 /* 2467 /*
2237 * Table with the specifications for an attribute number. 2468 * Table with the specifications for an attribute number.