2 Copyright (C) 1994 Miguel de Icaza.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23 #include "setup.h" /* For the externs */
26 /* Set to force black and white display at program startup */
27 int disable_colors
= 0;
29 /* Set if we are actually using colors */
32 /* Color styles for normal and error dialogs */
33 int dialog_colors
[4];
36 #define ELEMENTS(arr) ( sizeof(arr) / sizeof((arr)[0]) )
39 # define color_map_fg(n) color_map[n].fg
40 # define color_map_bg(n) color_map[n].bg
42 # define color_map_fg(n) (color_map[n].fg & COLOR_WHITE)
43 # define color_map_bg(n) (color_map[n].bg & COLOR_WHITE)
47 char *name
; /* Name of the entry */
48 CTYPE fg
; /* foreground color */
49 CTYPE bg
; /* background color */
52 struct colorpair color_map
[] = {
53 { "normal=", 0, 0 }, /* normal */ /* 1 */
54 { "selected=", 0, 0 }, /* selected */
55 { "marked=", 0, 0 }, /* marked */
56 { "markselect=", 0, 0 }, /* marked/selected */
57 { "errors=", 0, 0 }, /* errors */
58 { "menu=", 0, 0 }, /* menu entry */
59 { "reverse=", 0, 0 }, /* reverse */
62 { "dnormal=", 0, 0 }, /* Dialog normal */ /* 8 */
63 { "dfocus=", 0, 0 }, /* Dialog focused */
64 { "dhotnormal=", 0, 0 }, /* Dialog normal/hot */
65 { "dhotfocus=", 0, 0 }, /* Dialog focused/hot */
67 { "viewunderline=", 0, 0 }, /* _\b? sequence in view, underline in editor */
68 { "menusel=", 0, 0 }, /* Menu selected color */ /* 13 */
69 { "menuhot=", 0, 0 }, /* Color for menu hotkeys */
70 { "menuhotsel=", 0, 0 }, /* Menu hotkeys/selected entry */
72 { "helpnormal=", 0, 0 }, /* Help normal */ /* 16 */
73 { "helpitalic=", 0, 0 }, /* Italic in help */
74 { "helpbold=", 0, 0 }, /* Bold in help */
75 { "helplink=", 0, 0 }, /* Not selected hyperlink */
76 { "helpslink=", 0, 0 }, /* Selected hyperlink */
78 { "gauge=", 0, 0 }, /* Color of the progress bar (percentage) *//* 21 */
81 /* Per file types colors */
82 { "directory=", 0, 0 }, /* 23 */
83 { "executable=", 0, 0 },
84 { "link=", 0, 0 }, /* symbolic link (neither stalled nor link to directory) */
85 { "stalledlink=",0, 0 }, /* stalled symbolic link */
87 { "special=", 0, 0 }, /* sockets, fifo */
88 { "core=", 0, 0 }, /* core files */ /* 29 */
90 { 0, 0, 0 }, /* not usable (DEFAULT_COLOR_INDEX) *//* 30 */
91 { 0, 0, 0 }, /* unused */
92 { 0, 0, 0 }, /* not usable (A_REVERSE) */
93 { 0, 0, 0 }, /* not usable (A_REVERSE_BOLD) */
95 /* editor colors start at 34 */
96 { "editnormal=", 0, 0 }, /* normal */ /* 34 */
97 { "editbold=", 0, 0 }, /* search->found */
98 { "editmarked=", 0, 0 }, /* marked/selected */
101 struct color_table_s
{
107 static struct color_table_s
const color_table
[] = {
108 { "black", COLOR_BLACK
},
109 { "gray", COLOR_BLACK
| A_BOLD
},
110 { "red", COLOR_RED
},
111 { "brightred", COLOR_RED
| A_BOLD
},
112 { "green", COLOR_GREEN
},
113 { "brightgreen", COLOR_GREEN
| A_BOLD
},
114 { "brown", COLOR_YELLOW
},
115 { "yellow", COLOR_YELLOW
| A_BOLD
},
116 { "blue", COLOR_BLUE
},
117 { "brightblue", COLOR_BLUE
| A_BOLD
},
118 { "magenta", COLOR_MAGENTA
},
119 { "brightmagenta", COLOR_MAGENTA
| A_BOLD
},
120 { "cyan", COLOR_CYAN
},
121 { "brightcyan", COLOR_CYAN
| A_BOLD
},
122 { "lightgray", COLOR_WHITE
},
123 { "white", COLOR_WHITE
| A_BOLD
},
124 { "default", 0 } /* hack for transparent background */
128 # define color_value(i) color_table [i].name
129 # define color_name(i) color_table [i].name
131 # define color_value(i) color_table [i].value
132 # define color_name(i) color_table [i].name
135 static void get_color (char *cpp
, CTYPE
*colp
)
139 for (i
= 0; i
< ELEMENTS(color_table
); i
++){
140 if (strcmp (cpp
, color_name (i
)) == 0){
141 *colp
= color_value (i
);
147 static void get_two_colors (char **cpp
, struct colorpair
*colorpairp
)
157 get_color (*cpp
, state
? &colorpairp
->bg
: &colorpairp
->fg
);
166 get_color (*cpp
, &colorpairp
->fg
);
171 get_color (*cpp
, state
? &colorpairp
->bg
: &colorpairp
->fg
);
174 static void configure_colors_string (char *the_color_string
)
176 char *color_string
, *p
;
179 if (!the_color_string
)
182 p
= color_string
= g_strdup (the_color_string
);
183 while (color_string
&& *color_string
){
184 while (*color_string
== ' ' || *color_string
== '\t')
188 for (i
= 0; i
< ELEMENTS(color_map
); i
++){
191 if (!color_map
[i
].name
)
193 klen
= strlen (color_map
[i
].name
);
195 if (strncmp (color_string
, color_map
[i
].name
, klen
) == 0){
196 color_string
+= klen
;
197 get_two_colors (&color_string
, &color_map
[i
]);
202 while (*color_string
&& *color_string
!= ':')
211 static void configure_colors (void)
213 extern char *command_line_colors
;
214 extern char *default_edition_colors
;
216 configure_colors_string (default_edition_colors
);
217 configure_colors_string (setup_color_string
);
218 configure_colors_string (term_color_string
);
219 configure_colors_string (getenv ("MC_COLOR_TABLE"));
220 configure_colors_string (command_line_colors
);
225 int attr_pairs
[MAX_PAIRS
];
229 load_dialog_colors (void)
231 dialog_colors
[0] = COLOR_NORMAL
;
232 dialog_colors
[1] = COLOR_FOCUS
;
233 dialog_colors
[2] = COLOR_HOT_NORMAL
;
234 dialog_colors
[3] = COLOR_HOT_FOCUS
;
236 alarm_colors
[0] = ERROR_COLOR
;
237 alarm_colors
[1] = REVERSE_COLOR
;
238 alarm_colors
[2] = ERROR_COLOR
;
239 alarm_colors
[3] = COLOR_HOT_NORMAL
;
242 void init_colors (void)
248 /* FIXME: if S-Lang is used, this function must be called regardless
249 of whether we are interested in its result */
250 hascolors
= has_colors ();
252 if (!disable_colors
&& hascolors
){
261 if (ELEMENTS (color_map
) > MAX_PAIRS
){
262 /* This message should only be seen by the developers */
264 "Too many defined colors, resize MAX_PAIRS on color.c");
267 #endif /* !HAVE_SLANG */
272 * We are relying on undocumented feature of
273 * S-Lang to make COLOR_PAIR(DEFAULT_COLOR_INDEX)
274 * the default fg/bg of the terminal.
275 * Hopefully, future versions of S-Lang will
276 * document this feature.
278 SLtt_set_color (DEFAULT_COLOR_INDEX
, NULL
, "default", "default");
280 /* Always white on black */
281 mc_init_pair(DEFAULT_COLOR_INDEX
, COLOR_WHITE
, COLOR_BLACK
);
282 #endif /* !HAVE_SLANG */
285 for (i
= 0; i
< ELEMENTS (color_map
); i
++){
286 if (!color_map
[i
].name
)
289 mc_init_pair (i
+1, color_map_fg(i
), color_map_bg(i
));
293 * ncurses doesn't remember bold attribute in the color pairs,
294 * so we should keep track of it in a separate array.
296 attr_pairs
[i
+1] = color_map
[i
].fg
& A_BOLD
;
297 #endif /* !HAVE_SLANG */
300 load_dialog_colors ();
303 /* Functions necessary to implement syntax highlighting */
305 static int max_index
= 0;
308 alloc_color_pair (CTYPE foreground
, CTYPE background
)
310 mc_init_pair (++max_index
, foreground
, background
);
314 static struct colors_avail
{
315 struct colors_avail
*next
;
318 } c
= { 0, 0, 0, 0 };
322 mc_init_pair (int index
, CTYPE foreground
, CTYPE background
)
324 /* hack for transparent background for Eterm, rxvt or else */
325 if (background
&& !strcmp (background
, "default"))
327 /* if foreground is default, I guess we should use normal fore-color. */
329 SLtt_set_color (index
, "", foreground
, background
);
330 if (index
> max_index
)
335 try_alloc_color_pair (char *fg
, char *bg
)
337 struct colors_avail
*p
= &c
;
339 c
.index
= EDITOR_NORMAL_COLOR_INDEX
;
341 if (((fg
&& p
->fg
) ? !strcmp (fg
, p
->fg
) : fg
== p
->fg
) != 0
342 && ((bg
&& p
->bg
) ? !strcmp (bg
, p
->bg
) : bg
== p
->bg
) != 0)
348 p
->next
= g_new (struct colors_avail
, 1);
351 p
->fg
= fg
? g_strdup (fg
) : 0;
352 p
->bg
= bg
? g_strdup (bg
) : 0;
354 /* Index in color_map array = COLOR_INDEX - 1 */
355 fg
= color_map
[EDITOR_NORMAL_COLOR_INDEX
- 1].fg
;
357 bg
= color_map
[EDITOR_NORMAL_COLOR_INDEX
- 1].bg
;
358 p
->index
= alloc_color_pair (fg
, bg
);
362 #else /* !HAVE_SLANG */
364 mc_init_pair (int index
, CTYPE foreground
, CTYPE background
)
366 init_pair (index
, foreground
, background
);
367 if (index
> max_index
)
372 try_alloc_color_pair (char *fg
, char *bg
)
374 int fg_index
, bg_index
;
376 struct colors_avail
*p
= &c
;
378 c
.index
= EDITOR_NORMAL_COLOR_INDEX
;
380 if (((fg
&& p
->fg
) ? !strcmp (fg
, p
->fg
) : fg
== p
->fg
) != 0
381 && ((bg
&& p
->bg
) ? !strcmp (bg
, p
->bg
) : bg
== p
->bg
) != 0)
387 p
->next
= g_new (struct colors_avail
, 1);
390 p
->fg
= fg
? g_strdup (fg
) : 0;
391 p
->bg
= bg
? g_strdup (bg
) : 0;
393 /* Index in color_map array = COLOR_INDEX - 1 */
394 fg_index
= color_map
[EDITOR_NORMAL_COLOR_INDEX
- 1].fg
;
396 get_color (fg
, &fg_index
);
399 bg_index
= color_map
[EDITOR_NORMAL_COLOR_INDEX
- 1].bg
;
401 get_color (bg
, &bg_index
);
403 bold_attr
= fg_index
& A_BOLD
;
404 fg_index
= fg_index
& COLOR_WHITE
;
405 bg_index
= bg_index
& COLOR_WHITE
;
407 p
->index
= alloc_color_pair (fg_index
, bg_index
);
408 attr_pairs
[p
->index
] = bold_attr
;
411 #endif /* !HAVE_SLANG */
414 dealloc_color_pairs (void)
416 struct colors_avail
*p
, *next
;
418 for (p
= c
.next
; p
; p
= next
) {