2 Copyright (C) 1994, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3 2007 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
25 #include <mhl/memory.h>
26 #include <mhl/string.h>
30 #include "setup.h" /* For the externs */
33 /* Set to force black and white display at program startup */
34 int disable_colors
= 0;
36 /* Set if we are actually using colors */
39 /* Color styles for normal and error dialogs */
40 int dialog_colors
[4];
43 #define ELEMENTS(arr) ( sizeof(arr) / sizeof((arr)[0]) )
46 # define color_map_fg(n) color_map[n].fg
47 # define color_map_bg(n) color_map[n].bg
49 # define color_map_fg(n) (color_map[n].fg & COLOR_WHITE)
50 # define color_map_bg(n) (color_map[n].bg & COLOR_WHITE)
54 const char *name
; /* Name of the entry */
55 CTYPE fg
; /* foreground color */
56 CTYPE bg
; /* background color */
59 static struct colorpair color_map
[] = {
60 { "normal=", 0, 0 }, /* normal */ /* 1 */
61 { "selected=", 0, 0 }, /* selected */
62 { "marked=", 0, 0 }, /* marked */
63 { "markselect=", 0, 0 }, /* marked/selected */
64 { "errors=", 0, 0 }, /* errors */
65 { "menu=", 0, 0 }, /* menu entry */
66 { "reverse=", 0, 0 }, /* reverse */
69 { "dnormal=", 0, 0 }, /* Dialog normal */ /* 8 */
70 { "dfocus=", 0, 0 }, /* Dialog focused */
71 { "dhotnormal=", 0, 0 }, /* Dialog normal/hot */
72 { "dhotfocus=", 0, 0 }, /* Dialog focused/hot */
74 { "viewunderline=", 0, 0 }, /* _\b? sequence in view, underline in editor */
75 { "menusel=", 0, 0 }, /* Menu selected color */ /* 13 */
76 { "menuhot=", 0, 0 }, /* Color for menu hotkeys */
77 { "menuhotsel=", 0, 0 }, /* Menu hotkeys/selected entry */
79 { "helpnormal=", 0, 0 }, /* Help normal */ /* 16 */
80 { "helpitalic=", 0, 0 }, /* Italic in help */
81 { "helpbold=", 0, 0 }, /* Bold in help */
82 { "helplink=", 0, 0 }, /* Not selected hyperlink */
83 { "helpslink=", 0, 0 }, /* Selected hyperlink */
85 { "gauge=", 0, 0 }, /* Color of the progress bar (percentage) *//* 21 */
88 /* Per file types colors */
89 { "directory=", 0, 0 }, /* 23 */
90 { "executable=", 0, 0 },
91 { "link=", 0, 0 }, /* symbolic link (neither stale nor link to directory) */
92 { "stalelink=", 0, 0 }, /* stale symbolic link */
94 { "special=", 0, 0 }, /* sockets, fifo */
95 { "core=", 0, 0 }, /* core files */ /* 29 */
97 { 0, 0, 0 }, /* not usable (DEFAULT_COLOR_INDEX) *//* 30 */
98 { 0, 0, 0 }, /* unused */
99 { 0, 0, 0 }, /* not usable (A_REVERSE) */
100 { 0, 0, 0 }, /* not usable (A_REVERSE_BOLD) */
102 /* editor colors start at 34 */
103 { "editnormal=", 0, 0 }, /* normal */ /* 34 */
104 { "editbold=", 0, 0 }, /* search->found */
105 { "editmarked=", 0, 0 }, /* marked/selected */
106 { "editwhitespace=", 0, 0 }, /* whitespace */
108 /* error dialog colors start at 38 */
109 { "errdhotnormal=", 0, 0 }, /* Error dialog normal/hot */ /* 38 */
110 { "errdhotfocus=", 0, 0 }, /* Error dialog focused/hot */
113 struct color_table_s
{
119 static struct color_table_s
const color_table
[] = {
120 { "black", COLOR_BLACK
},
121 { "gray", COLOR_BLACK
| A_BOLD
},
122 { "red", COLOR_RED
},
123 { "brightred", COLOR_RED
| A_BOLD
},
124 { "green", COLOR_GREEN
},
125 { "brightgreen", COLOR_GREEN
| A_BOLD
},
126 { "brown", COLOR_YELLOW
},
127 { "yellow", COLOR_YELLOW
| A_BOLD
},
128 { "blue", COLOR_BLUE
},
129 { "brightblue", COLOR_BLUE
| A_BOLD
},
130 { "magenta", COLOR_MAGENTA
},
131 { "brightmagenta", COLOR_MAGENTA
| A_BOLD
},
132 { "cyan", COLOR_CYAN
},
133 { "brightcyan", COLOR_CYAN
| A_BOLD
},
134 { "lightgray", COLOR_WHITE
},
135 { "white", COLOR_WHITE
| A_BOLD
},
136 { "default", 0 } /* default color of the terminal */
139 static const char *default_colors
=
140 "normal=lightgray,blue:"
141 "selected=black,cyan:"
142 "marked=yellow,blue:"
143 "markselect=yellow,cyan:"
146 "reverse=black,lightgray:"
147 "dnormal=black,lightgray:"
149 "dhotnormal=blue,lightgray:"
150 "dhotfocus=blue,cyan:"
151 "viewunderline=brightred,blue:"
152 "menuhot=yellow,cyan:"
153 "menusel=white,black:"
154 "menuhotsel=yellow,black:"
155 "helpnormal=black,lightgray:"
156 "helpitalic=red,lightgray:"
157 "helpbold=blue,lightgray:"
158 "helplink=black,cyan:"
159 "helpslink=yellow,blue:"
162 "directory=white,blue:"
163 "executable=brightgreen,blue:"
164 "link=lightgray,blue:"
165 "stalelink=brightred,blue:"
166 "device=brightmagenta,blue:"
168 "special=black,blue:"
169 "editnormal=lightgray,blue:"
170 "editbold=yellow,blue:"
171 "editmarked=black,cyan:"
172 "editwhitespace=brightblue,blue:"
173 "errdhotnormal=yellow,red:"
174 "errdhotfocus=yellow,lightgray";
177 # define color_value(i) color_table [i].name
178 # define color_name(i) color_table [i].name
180 # define color_value(i) color_table [i].value
181 # define color_name(i) color_table [i].name
184 static void get_color (const char *cpp
, CTYPE
*colp
)
188 for (i
= 0; i
< ELEMENTS(color_table
); i
++){
189 if (strcmp (cpp
, color_name (i
)) == 0){
190 *colp
= color_value (i
);
196 static void get_two_colors (char **cpp
, struct colorpair
*colorpairp
)
206 get_color (*cpp
, state
? &colorpairp
->bg
: &colorpairp
->fg
);
215 get_color (*cpp
, &colorpairp
->fg
);
220 get_color (*cpp
, state
? &colorpairp
->bg
: &colorpairp
->fg
);
223 static void configure_colors_string (const char *the_color_string
)
225 char *color_string
, *p
;
229 if (!the_color_string
)
232 p
= color_string
= g_strdup (the_color_string
);
233 while (color_string
&& *color_string
){
234 while (*color_string
== ' ' || *color_string
== '\t')
238 for (i
= 0; i
< ELEMENTS(color_map
); i
++){
241 if (!color_map
[i
].name
)
243 klen
= strlen (color_map
[i
].name
);
245 if (strncmp (color_string
, color_map
[i
].name
, klen
) == 0){
246 color_string
+= klen
;
247 get_two_colors (&color_string
, &color_map
[i
]);
252 while (*color_string
&& *color_string
!= ':')
261 static void configure_colors (void)
263 extern char *command_line_colors
;
265 configure_colors_string (default_colors
);
266 configure_colors_string (setup_color_string
);
267 configure_colors_string (term_color_string
);
268 configure_colors_string (getenv ("MC_COLOR_TABLE"));
269 configure_colors_string (command_line_colors
);
274 int attr_pairs
[MAX_PAIRS
];
278 load_dialog_colors (void)
280 dialog_colors
[0] = COLOR_NORMAL
;
281 dialog_colors
[1] = COLOR_FOCUS
;
282 dialog_colors
[2] = COLOR_HOT_NORMAL
;
283 dialog_colors
[3] = COLOR_HOT_FOCUS
;
285 alarm_colors
[0] = ERROR_COLOR
;
286 alarm_colors
[1] = REVERSE_COLOR
;
287 alarm_colors
[2] = ERROR_HOT_NORMAL
;
288 alarm_colors
[3] = ERROR_HOT_FOCUS
;
291 void init_colors (void)
297 /* FIXME: if S-Lang is used, this function must be called regardless
298 of whether we are interested in its result */
299 hascolors
= has_colors ();
301 if (!disable_colors
&& hascolors
){
310 if (ELEMENTS (color_map
) > MAX_PAIRS
){
311 /* This message should only be seen by the developers */
313 "Too many defined colors, resize MAX_PAIRS on color.c");
316 #endif /* !HAVE_SLANG */
321 * We are relying on undocumented feature of
322 * S-Lang to make COLOR_PAIR(DEFAULT_COLOR_INDEX)
323 * the default fg/bg of the terminal.
324 * Hopefully, future versions of S-Lang will
325 * document this feature.
327 SLtt_set_color (DEFAULT_COLOR_INDEX
, NULL
, "default", "default");
329 /* Always white on black */
330 mc_init_pair(DEFAULT_COLOR_INDEX
, COLOR_WHITE
, COLOR_BLACK
);
331 #endif /* !HAVE_SLANG */
334 for (i
= 0; i
< ELEMENTS (color_map
); i
++){
335 if (!color_map
[i
].name
)
338 mc_init_pair (i
+1, color_map_fg(i
), color_map_bg(i
));
342 * ncurses doesn't remember bold attribute in the color pairs,
343 * so we should keep track of it in a separate array.
345 attr_pairs
[i
+1] = color_map
[i
].fg
& A_BOLD
;
346 #endif /* !HAVE_SLANG */
349 load_dialog_colors ();
352 /* Functions necessary to implement syntax highlighting */
354 static int max_index
= 0;
357 alloc_color_pair (CTYPE foreground
, CTYPE background
)
359 mc_init_pair (++max_index
, foreground
, background
);
363 static struct colors_avail
{
364 struct colors_avail
*next
;
367 } c
= { 0, 0, 0, 0 };
371 mc_init_pair (int index
, CTYPE foreground
, CTYPE background
)
374 background
= "default";
377 foreground
= "default";
379 SLtt_set_color (index
, "", (char *) foreground
, (char *) background
);
380 if (index
> max_index
)
385 try_alloc_color_pair (const char *fg
, const char *bg
)
387 struct colors_avail
*p
= &c
;
389 c
.index
= EDITOR_NORMAL_COLOR_INDEX
;
391 if (((fg
&& p
->fg
) ? !strcmp (fg
, p
->fg
) : fg
== p
->fg
) != 0
392 && ((bg
&& p
->bg
) ? !strcmp (bg
, p
->bg
) : bg
== p
->bg
) != 0)
398 p
->next
= g_new (struct colors_avail
, 1);
401 p
->fg
= fg
? g_strdup (fg
) : 0;
402 p
->bg
= bg
? g_strdup (bg
) : 0;
404 /* Index in color_map array = COLOR_INDEX - 1 */
405 fg
= color_map
[EDITOR_NORMAL_COLOR_INDEX
- 1].fg
;
407 bg
= color_map
[EDITOR_NORMAL_COLOR_INDEX
- 1].bg
;
408 p
->index
= alloc_color_pair (fg
, bg
);
412 #else /* !HAVE_SLANG */
414 mc_init_pair (int index
, CTYPE foreground
, CTYPE background
)
416 init_pair (index
, foreground
, background
);
417 if (index
> max_index
)
422 try_alloc_color_pair (const char *fg
, const char *bg
)
424 int fg_index
, bg_index
;
426 struct colors_avail
*p
= &c
;
428 c
.index
= EDITOR_NORMAL_COLOR_INDEX
;
430 if (((fg
&& p
->fg
) ? !strcmp (fg
, p
->fg
) : fg
== p
->fg
) != 0
431 && ((bg
&& p
->bg
) ? !strcmp (bg
, p
->bg
) : bg
== p
->bg
) != 0)
437 p
->next
= g_new (struct colors_avail
, 1);
440 p
->fg
= fg
? g_strdup (fg
) : 0;
441 p
->bg
= bg
? g_strdup (bg
) : 0;
443 /* Index in color_map array = COLOR_INDEX - 1 */
444 fg_index
= color_map
[EDITOR_NORMAL_COLOR_INDEX
- 1].fg
;
446 get_color (fg
, &fg_index
);
449 bg_index
= color_map
[EDITOR_NORMAL_COLOR_INDEX
- 1].bg
;
451 get_color (bg
, &bg_index
);
453 bold_attr
= fg_index
& A_BOLD
;
454 fg_index
= fg_index
& COLOR_WHITE
;
455 bg_index
= bg_index
& COLOR_WHITE
;
457 p
->index
= alloc_color_pair (fg_index
, bg_index
);
458 attr_pairs
[p
->index
] = bold_attr
;
461 #endif /* !HAVE_SLANG */
466 struct colors_avail
*p
, *next
;
468 for (p
= c
.next
; p
; p
= next
) {