Mercurial > vim
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. |