From 4afc04eedc23445c1189c94710d22625f38226b5 Mon Sep 17 00:00:00 2001 From: Slava Zanko Date: Wed, 2 Sep 2009 02:07:50 +0300 Subject: [PATCH] Ticket #418: File coloring Added support of filenames highlighting in panels. Now rules of highlighting described into external file filehighlight.ini Number of highlight rules is unlimited (in opposite to X-Stranger patch). Highlight will made by: * file type (directory, regular, symlink, special device etc.) * extensions of filenames (ends of filenames) * regular expressions Big thanks to X-Stranger for idea and to Alexey Kaminsky for testing. Signed-off-by: Slava Zanko --- configure.ac | 1 + doc/filehighlight.txt | 30 +++ misc/Makefile.am | 1 + misc/filehighlight.ini | 63 +++++++ src/Makefile.am | 5 +- src/filehighlight/Makefile.am | 14 ++ src/filehighlight/common.c | 128 +++++++++++++ src/filehighlight/fhl.h | 32 ++++ src/filehighlight/get-color.c | 251 +++++++++++++++++++++++++ src/filehighlight/ini-file-read.c | 303 ++++++++++++++++++++++++++++++ src/filehighlight/internal.h | 55 ++++++ src/main.c | 5 + src/main.h | 4 + src/screen.c | 42 +---- src/tty/color-internal.c | 19 +- src/tty/color-internal.h | 7 - src/tty/color.h | 26 +-- 17 files changed, 912 insertions(+), 74 deletions(-) create mode 100644 doc/filehighlight.txt create mode 100644 misc/filehighlight.ini create mode 100644 src/filehighlight/Makefile.am create mode 100644 src/filehighlight/common.c create mode 100644 src/filehighlight/fhl.h create mode 100644 src/filehighlight/get-color.c create mode 100644 src/filehighlight/ini-file-read.c create mode 100644 src/filehighlight/internal.h diff --git a/configure.ac b/configure.ac index 159f24157..691a7a916 100644 --- a/configure.ac +++ b/configure.ac @@ -559,6 +559,7 @@ misc/Makefile misc/mc.ext src/Makefile +src/filehighlight/Makefile src/mcconfig/Makefile src/search/Makefile src/tty/Makefile diff --git a/doc/filehighlight.txt b/doc/filehighlight.txt new file mode 100644 index 000000000..364e164f4 --- /dev/null +++ b/doc/filehighlight.txt @@ -0,0 +1,30 @@ +Main section [filehighlight] contain key names as highlight groups and values as color pairs +color pair described as 'foreground;background'. 'background' may be omited. + +other sections describe filegroup of highlight. +Keys in these groups: + +type + - file type. if present, all other option ignored; +regexp + - regular expression. If present, 'extensions' option ignored; +extensions + - list of extensions of files. Separated by ';' sign. + +'type' key may have values: + +- FILE - all files. + - FILE_EXE +- DIR - all directoryes + - LINK_DIR +- LINK (all links except stale link) + - HARDLINK + - SYMLINK +- STALE_LINK +- DEVICE (all device files) + - DEVICE_BLOCK + - DEVICE_CHAR +- SPECIAL (all special files) + - SPECIAL_SOCKET + - SPECIAL_FIFO + - SPECIAL_DOOR diff --git a/misc/Makefile.am b/misc/Makefile.am index 19ab73171..14d51cf0c 100644 --- a/misc/Makefile.am +++ b/misc/Makefile.am @@ -11,6 +11,7 @@ LIBFILES_CONST = \ edit.indent.rc \ edit.spell.rc \ mc.lib \ + filehighlight.ini \ mc.menu diff --git a/misc/filehighlight.ini b/misc/filehighlight.ini new file mode 100644 index 000000000..1e17e3814 --- /dev/null +++ b/misc/filehighlight.ini @@ -0,0 +1,63 @@ +[filehighlight] + directory=white; + executable=brightgreen; + symlink=lightgray; + stalelink=brightred; + device=brightmagenta; + special=black; + core=red; + + temp=gray; + archive=brightmagenta; + hidden=black; + doc=brown; + source=cyan; + media=green; + graph=brightcyan; + database=brightred; + +[executable] + type=FILE_EXE + +[directory] + type=DIR + +[symlink] + type=SYMLINK + +[stalelink] + type=STALE_LINK + +[device] + type=DEVICE + +[special] + type=SPECIAL + +[core] + regexp=^core\\.\\d+$ + +[temp] + extensions=tmp;$$$;~;bak + +[archive] + extensions=gz;bz2;tar;tgz;rpm;Z;rar;zip;arj;cab;lzh;lha;zoo;arc;ark + +[hidden] + regexp=^\\..* + +[doc] + extensions=txt;doc;rtf;diz;ctl;me;ps;pdf;xml;xsd;xslt;dtd;html;shtml;htm;mail;msg;lsm;po;nroff;man;tex;sgml;css;text;letter + +[source] + extensions=c;h;cc;hh;cpp;hpp;asm;py;pl;pm;inc;cgi;php;phps;js;java;jav;jasm;sh;bash;diff;patch;pas;tcl;tk;awk;m4;st;mak;sl;ada;caml;ml;mli;mly;mll;mlp;sas;prg + +[media] + extensions=mp2;mp3;mpg;ogg;mpeg;wav;avi;asf;mov;mol;mpl;xm;mod;it;med;mid;midi;s3m;umx;vob + +[graph] + extensions=jpg;jpeg;gif;png;tif;pcx;bmp;xpm;xbm;eps;pic;rle;ico;wmf;omf;ai;cdr + +[database] + extensions=dbf;mdn;db;mdb;dat;fox;dbx;mdx;sql;mssql;msql;ssql;pgsql;xls;cdx;dbi + diff --git a/src/Makefile.am b/src/Makefile.am index ed7ef1ede..969422cda 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = mcconfig search tty viewer +SUBDIRS = mcconfig search tty viewer filehighlight AM_CFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) $(PCRE_CFLAGS) @@ -43,8 +43,9 @@ MCCONFIGLIB = mcconfig/libmcconfig.la SEARCHLIB = search/libsearch.la TTYLIB = tty/libmctty.la VIEWERLIB = viewer/libmcviewer.la +FILEHIGHLIGHTLIB=filehighlight/libmcfilehighlight.la -mc_LDADD = $(EDITLIB) $(VFSLIB) \ +mc_LDADD = $(EDITLIB) $(VFSLIB) $(FILEHIGHLIGHTLIB) \ $(MCCONFIGLIB) $(SEARCHLIB) $(TTYLIB) $(VIEWERLIB) \ $(INTLLIBS) $(MCLIBS) $(SLANGLIB) $(LIBICONV) $(GLIB_LIBS) diff --git a/src/filehighlight/Makefile.am b/src/filehighlight/Makefile.am new file mode 100644 index 000000000..dba81d39b --- /dev/null +++ b/src/filehighlight/Makefile.am @@ -0,0 +1,14 @@ +noinst_LTLIBRARIES = libmcfilehighlight.la + +libmcfilehighlight_la_SOURCES = \ + common.c \ + fhl.h \ + get-color.c \ + ini-file-read.c \ + internal.h + +libmcfilehighlight_la_CFLAGS=-I../ -I$(top_srcdir)/src \ + $(GLIB_CFLAGS) $(PCRE_CFLAGS) \ + -DDATADIR=\""$(pkgdatadir)/"\" -DLOCALEDIR=\""$(localedir)"\" + +libmcfilehighlight_la_LIBADD = $(PCRE_LIBS) diff --git a/src/filehighlight/common.c b/src/filehighlight/common.c new file mode 100644 index 000000000..ced107931 --- /dev/null +++ b/src/filehighlight/common.c @@ -0,0 +1,128 @@ +/* + File highlight plugin. + Interface functions + + Copyright (C) 2009 The Free Software Foundation, Inc. + + Written by: + Slava Zanko , 2009. + + This file is part of the Midnight Commander. + + The Midnight Commander is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Midnight Commander is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. + */ + +#include + + +#include "../src/global.h" +#include "../src/filehighlight/fhl.h" +#include "internal.h" + +/*** global variables ****************************************************************************/ + +/*** file scope macro definitions ****************************************************************/ + +/*** file scope type declarations ****************************************************************/ + +/*** file scope variables ************************************************************************/ + +/*** file scope functions ************************************************************************/ +/* --------------------------------------------------------------------------------------------- */ + +void +mc_fhl_array_free (mc_fhl_t * fhl) +{ + guint i; + mc_fhl_filter_t *mc_filter; + + if (fhl->filters == NULL) + return; + + for (i = 0; i < fhl->filters->len; i++) { + mc_filter = (mc_fhl_filter_t *) g_ptr_array_index (fhl->filters, i); + + g_free (mc_filter->fgcolor); + g_free (mc_filter->bgcolor); + + if (mc_filter->search_condition != NULL) + mc_search_free (mc_filter->search_condition); + + g_free (mc_filter); + } + g_ptr_array_free (fhl->filters, TRUE); + fhl->filters = NULL; +} + +/* --------------------------------------------------------------------------------------------- */ +/*** public functions ****************************************************************************/ +/* --------------------------------------------------------------------------------------------- */ + +mc_fhl_t * +mc_fhl_new (gboolean need_auto_fill) +{ + + mc_fhl_t *fhl; + + fhl = g_new0 (mc_fhl_t, 1); + if (fhl == NULL) + return NULL; + + if (!need_auto_fill) + return fhl; + + if (!mc_fhl_init_from_standart_files (fhl)) { + g_free (fhl); + return NULL; + } + + if (!mc_fhl_parce_ini_file (fhl)) { + mc_fhl_free (&fhl); + return NULL; + } + + return fhl; +} + +/* --------------------------------------------------------------------------------------------- */ + +void +mc_fhl_free (mc_fhl_t ** fhl) +{ + if (fhl == NULL || *fhl == NULL) + return; + + mc_fhl_clear (*fhl); + + g_free (*fhl); + *fhl = NULL; +} + +/* --------------------------------------------------------------------------------------------- */ + +void +mc_fhl_clear (mc_fhl_t * fhl) +{ + if (fhl == NULL) + return; + + if (fhl->config) + mc_config_deinit (fhl->config); + + mc_fhl_array_free (fhl); +} + +/* --------------------------------------------------------------------------------------------- */ diff --git a/src/filehighlight/fhl.h b/src/filehighlight/fhl.h new file mode 100644 index 000000000..4f91762ba --- /dev/null +++ b/src/filehighlight/fhl.h @@ -0,0 +1,32 @@ +#ifndef MC__FILEHIGHLIGHT_H +#define MC__FILEHIGHLIGHT_H + +#include "../../src/mcconfig/mcconfig.h" +#include "../../src/search/search.h" +#include "../src/dir.h" + +/*** typedefs(not structures) and defined constants **********************************************/ + +/*** enums ***************************************************************************************/ + +/*** structures declarations (and typedefs of structures)*****************************************/ + +typedef struct mc_fhl_struct { + mc_config_t *config; + GPtrArray *filters; +} mc_fhl_t; + +/*** global variables defined in .c file *********************************************************/ + +/*** declarations of public functions ************************************************************/ + +mc_fhl_t *mc_fhl_new (gboolean); +void mc_fhl_free (mc_fhl_t **); + +int mc_fhl_get_color (mc_fhl_t *, file_entry *); + +gboolean mc_fhl_read_ini_file (mc_fhl_t *, const gchar *); +gboolean mc_fhl_parce_ini_file (mc_fhl_t *); +void mc_fhl_clear (mc_fhl_t *); + +#endif diff --git a/src/filehighlight/get-color.c b/src/filehighlight/get-color.c new file mode 100644 index 000000000..6326ed3ea --- /dev/null +++ b/src/filehighlight/get-color.c @@ -0,0 +1,251 @@ +/* + File highlight plugin. + Interface functions. get color pair index for highlighted file. + + Copyright (C) 2009 The Free Software Foundation, Inc. + + Written by: + Slava Zanko , 2009. + + This file is part of the Midnight Commander. + + The Midnight Commander is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Midnight Commander is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. + */ + +#include +#include + + +#include "../src/global.h" +#include "../src/util.h" +#include "../src/tty/color.h" +#include "../src/filehighlight/fhl.h" +#include "internal.h" + +/*** global variables ****************************************************************************/ + +/*** file scope macro definitions ****************************************************************/ + +/*** file scope type declarations ****************************************************************/ + +/*** file scope variables ************************************************************************/ + +/*** file scope functions ************************************************************************/ +/* --------------------------------------------------------------------------------------------- */ +/*inline functions*/ +inline static gboolean +mc_fhl_is_file (file_entry * fe) +{ + return S_ISREG (fe->st.st_mode); +} + +inline static gboolean +mc_fhl_is_file_exec (file_entry * fe) +{ + return is_exe (fe->st.st_mode); +} + +inline static gboolean +mc_fhl_is_dir (file_entry * fe) +{ + return S_ISDIR (fe->st.st_mode); +} + +inline static gboolean +mc_fhl_is_link (file_entry * fe) +{ + return S_ISLNK (fe->st.st_mode); +} + +inline static gboolean +mc_fhl_is_link_to_dir (file_entry * fe) +{ + return mc_fhl_is_link (fe) && (fe->f.link_to_dir); +} + +inline static gboolean +mc_fhl_is_stale_link (file_entry * fe) +{ + return mc_fhl_is_link (fe) && (fe->f.stale_link); +} + +inline static gboolean +mc_fhl_is_device_char (file_entry * fe) +{ + return S_ISCHR (fe->st.st_mode); +} + +inline static gboolean +mc_fhl_is_device_block (file_entry * fe) +{ + return S_ISBLK (fe->st.st_mode); +} + +inline static gboolean +mc_fhl_is_special_socket (file_entry * fe) +{ + return S_ISSOCK (fe->st.st_mode); +} + +inline static gboolean +mc_fhl_is_special_fifo (file_entry * fe) +{ + return S_ISFIFO (fe->st.st_mode); +} + +inline static gboolean +mc_fhl_is_special_door (file_entry * fe) +{ + return S_ISDOOR (fe->st.st_mode); +} + + +inline static gboolean +mc_fhl_is_special (file_entry * fe) +{ + return + (mc_fhl_is_special_socket (fe) || mc_fhl_is_special_fifo (fe) || mc_fhl_is_special_door (fe) + ); +} + + +/* --------------------------------------------------------------------------------------------- */ + +static int +mc_fhl_get_color_filetype (mc_fhl_filter_t * mc_filter, mc_fhl_t * fhl, file_entry * fe) +{ + gboolean my_color = FALSE; + + switch (mc_filter->file_type) { + case MC_FLHGH_FTYPE_T_FILE: + if (mc_fhl_is_file (fe)) + my_color = TRUE; + break; + case MC_FLHGH_FTYPE_T_FILE_EXE: + if ((mc_fhl_is_file (fe)) && (mc_fhl_is_file_exec (fe))) + my_color = TRUE; + break; + case MC_FLHGH_FTYPE_T_DIR: + if (mc_fhl_is_dir (fe) || mc_fhl_is_link_to_dir (fe)) + my_color = TRUE; + break; + case MC_FLHGH_FTYPE_T_LINK_DIR: + if (mc_fhl_is_link_to_dir (fe)) + my_color = TRUE; + break; + case MC_FLHGH_FTYPE_T_LINK: + if (mc_fhl_is_link (fe)) + my_color = TRUE; + break; + case MC_FLHGH_FTYPE_T_HARDLINK: + /*TODO: hanlde it */ + if (mc_fhl_is_link (fe)) + my_color = TRUE; + break; + case MC_FLHGH_FTYPE_T_SYMLINK: + /*TODO: hanlde it */ + if (mc_fhl_is_link (fe)) + my_color = TRUE; + break; + case MC_FLHGH_FTYPE_T_STALE_LINK: + if (mc_fhl_is_stale_link (fe)) + my_color = TRUE; + break; + case MC_FLHGH_FTYPE_T_DEVICE: + if ((mc_fhl_is_device_char (fe)) || (mc_fhl_is_device_block (fe))) + my_color = TRUE; + break; + case MC_FLHGH_FTYPE_T_DEVICE_BLOCK: + if (mc_fhl_is_device_block (fe)) + my_color = TRUE; + break; + case MC_FLHGH_FTYPE_T_DEVICE_CHAR: + if (mc_fhl_is_device_char (fe)) + my_color = TRUE; + break; + case MC_FLHGH_FTYPE_T_SPECIAL: + if (mc_fhl_is_special (fe)) + my_color = TRUE; + break; + case MC_FLHGH_FTYPE_T_SPECIAL_SOCKET: + if (mc_fhl_is_special_socket (fe)) + my_color = TRUE; + break; + case MC_FLHGH_FTYPE_T_SPECIAL_FIFO: + if (mc_fhl_is_special_fifo (fe)) + my_color = TRUE; + break; + case MC_FLHGH_FTYPE_T_SPECIAL_DOOR: + if (mc_fhl_is_special_door (fe)) + my_color = TRUE; + break; + } + + return (my_color) ? mc_filter->color_pair_index : -1; +} + +/* --------------------------------------------------------------------------------------------- */ + +static int +mc_fhl_get_color_regexp (mc_fhl_filter_t * mc_filter, mc_fhl_t * fhl, file_entry * fe) +{ + if (mc_filter->search_condition == NULL) + return -1; + + if (mc_search_run (mc_filter->search_condition, fe->fname, 0, strlen (fe->fname), NULL)) + return mc_filter->color_pair_index; + + return -1; +} + +/* --------------------------------------------------------------------------------------------- */ + +/* --------------------------------------------------------------------------------------------- */ +/*** public functions ****************************************************************************/ +/* --------------------------------------------------------------------------------------------- */ + + +int +mc_fhl_get_color (mc_fhl_t * fhl, file_entry * fe) +{ + guint i; + mc_fhl_filter_t *mc_filter; + int ret; + + + if (fhl == NULL) + return NORMAL_COLOR; + + for (i = 0; i < fhl->filters->len; i++) { + mc_filter = (mc_fhl_filter_t *) g_ptr_array_index (fhl->filters, i); + switch (mc_filter->type) { + case MC_FLHGH_T_FTYPE: + ret = mc_fhl_get_color_filetype (mc_filter, fhl, fe); + if (ret > 0) + return -ret; + break; + case MC_FLHGH_T_EXT: + case MC_FLHGH_T_FREGEXP: + ret = mc_fhl_get_color_regexp (mc_filter, fhl, fe); + if (ret > 0) + return -ret; + break; + } + } + return NORMAL_COLOR; +} + +/* --------------------------------------------------------------------------------------------- */ diff --git a/src/filehighlight/ini-file-read.c b/src/filehighlight/ini-file-read.c new file mode 100644 index 000000000..09e53a928 --- /dev/null +++ b/src/filehighlight/ini-file-read.c @@ -0,0 +1,303 @@ +/* + File highlight plugin. + Reading and parce rules from ini-files + + Copyright (C) 2009 The Free Software Foundation, Inc. + + Written by: + Slava Zanko , 2009. + + This file is part of the Midnight Commander. + + The Midnight Commander is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Midnight Commander is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. + */ + +#include +#include + +#include "../src/global.h" +#include "../src/main.h" +#include "../src/strescape.h" +#include "../src/tty/color.h" +#include "../src/filehighlight/fhl.h" +#include "internal.h" + +/*** global variables ****************************************************************************/ + +/*** file scope macro definitions ****************************************************************/ + +#define mc_fhl_INI_FILE "filehighlight.ini" + +/*** file scope type declarations ****************************************************************/ + +/*** file scope variables ************************************************************************/ + +/*** file scope functions ************************************************************************/ +/* --------------------------------------------------------------------------------------------- */ + +static void +mc_fhl_parce_fill_color_info (mc_fhl_filter_t * mc_filter, mc_fhl_t * fhl, const gchar * group_name) +{ + gchar **colors; + gsize colors_size; + + colors = mc_config_get_string_list (fhl->config, "filehighlight", group_name, &colors_size); + + if (colors == NULL) + return; + + if (colors[0] == NULL) { + g_strfreev (colors); + return; + } + + mc_filter->fgcolor = g_strdup (colors[0]); + + if (colors[1] == NULL) + mc_filter->bgcolor = NULL; + else + mc_filter->bgcolor = g_strdup (colors[1]); + + g_strfreev (colors); + + mc_filter->color_pair_index = tty_try_alloc_color_pair (mc_filter->fgcolor, mc_filter->bgcolor); +} + +/* --------------------------------------------------------------------------------------------- */ + +static gboolean +mc_fhl_parce_get_file_type_id (mc_fhl_t * fhl, const gchar * group_name) +{ + mc_fhl_filter_t *mc_filter; + + const gchar *types[] = { + "FILE", "FILE_EXE", + "DIR", "LINK_DIR", + "LINK", "HARDLINK", "SYMLINK", + "STALE_LINK", + "DEVICE", "DEVICE_BLOCK", "DEVICE_CHAR", + "SPECIAL", "SPECIAL_SOCKET", "SPECIAL_FIFO", "SPECIAL_DOOR", + NULL + }; + int i; + gchar *param_type = mc_config_get_string (fhl->config, group_name, "type", ""); + + if (*param_type == '\0') { + g_free (param_type); + return FALSE; + } + + for (i = 0; types[i] != NULL; i++) { + if (strcmp (types[i], param_type) == 0) + break; + } + g_free (param_type); + if (types[i] == NULL) + return FALSE; + + mc_filter = g_new0 (mc_fhl_filter_t, 1); + mc_filter->type = MC_FLHGH_T_FTYPE; + mc_filter->file_type = (mc_flhgh_ftype_type) i; + mc_fhl_parce_fill_color_info (mc_filter, fhl, group_name); + + g_ptr_array_add (fhl->filters, (gpointer) mc_filter); + return TRUE; +} + +/* --------------------------------------------------------------------------------------------- */ + +static gboolean +mc_fhl_parce_get_regexp (mc_fhl_t * fhl, const gchar * group_name) +{ + mc_fhl_filter_t *mc_filter; + gchar *regexp = mc_config_get_string (fhl->config, group_name, "regexp", ""); + + if (*regexp == '\0') { + g_free (regexp); + return FALSE; + } + + mc_filter = g_new0 (mc_fhl_filter_t, 1); + mc_filter->type = MC_FLHGH_T_FREGEXP; + mc_filter->search_condition = mc_search_new (regexp, -1); + mc_filter->search_condition->is_case_sentitive = TRUE; + mc_filter->search_condition->search_type = MC_SEARCH_T_REGEX; + + mc_fhl_parce_fill_color_info (mc_filter, fhl, group_name); + g_ptr_array_add (fhl->filters, (gpointer) mc_filter); + g_free (regexp); + return TRUE; + +} + +/* --------------------------------------------------------------------------------------------- */ + +static gboolean +mc_fhl_parce_get_extensions (mc_fhl_t * fhl, const gchar * group_name) +{ + mc_fhl_filter_t *mc_filter; + gchar **exts, **exts_orig; + gchar *esc_ext; + gsize exts_size; + GString *buf = g_string_new (""); + + exts_orig = exts = + mc_config_get_string_list (fhl->config, group_name, "extensions", &exts_size); + + if (exts_orig == NULL) + return FALSE; + + if (exts_orig[0] == NULL) { + g_strfreev (exts_orig); + return FALSE; + } + + while (*exts != NULL) { + esc_ext = strutils_regex_escape (*exts); + if (buf->len != 0) + g_string_append_c (buf, '|'); + g_string_append (buf, esc_ext); + g_free (esc_ext); + exts++; + } + g_strfreev (exts_orig); + esc_ext = g_string_free (buf, FALSE); + buf = g_string_new (".*\\.("); + g_string_append (buf, esc_ext); + g_string_append (buf, ")$"); + g_free (esc_ext); + + mc_filter = g_new0 (mc_fhl_filter_t, 1); + mc_filter->type = MC_FLHGH_T_FREGEXP; + mc_filter->search_condition = mc_search_new (buf->str, -1); + mc_filter->search_condition->is_case_sentitive = TRUE; + mc_filter->search_condition->search_type = MC_SEARCH_T_REGEX; + + mc_fhl_parce_fill_color_info (mc_filter, fhl, group_name); + g_ptr_array_add (fhl->filters, (gpointer) mc_filter); + g_string_free (buf, TRUE); + return TRUE; +} + +/* --------------------------------------------------------------------------------------------- */ +/*** public functions ****************************************************************************/ +/* --------------------------------------------------------------------------------------------- */ + + +gboolean +mc_fhl_read_ini_file (mc_fhl_t * fhl, const gchar * filename) +{ + if (fhl == NULL || filename == NULL || !exist_file (filename)) + return FALSE; + + if (fhl->config) { + + if (!mc_config_read_file (fhl->config, filename)) + return FALSE; + + return TRUE; + } + + fhl->config = mc_config_init (filename); + + if (fhl->config == NULL) + return FALSE; + + return TRUE; +} + + +/* --------------------------------------------------------------------------------------------- */ + +gboolean +mc_fhl_init_from_standart_files (mc_fhl_t * fhl) +{ + gchar *name; + gchar *user_mc_dir; + + /* ${datadir}/mc/filehighlight.ini */ + name = concat_dir_and_file (mc_home_alt, mc_fhl_INI_FILE); + if (exist_file (name) && (!mc_fhl_read_ini_file (fhl, name))) { + g_free (name); + return FALSE; + } + g_free (name); + + /* ${sysconfdir}/mc/filehighlight.ini */ + name = concat_dir_and_file (mc_home, mc_fhl_INI_FILE); + if (exist_file (name) && (!mc_fhl_read_ini_file (fhl, name))) { + g_free (name); + return FALSE; + } + g_free (name); + + /* ~/.mc/filehighlight.ini */ + user_mc_dir = concat_dir_and_file (home_dir, MC_BASE); + name = concat_dir_and_file (user_mc_dir, mc_fhl_INI_FILE); + g_free (user_mc_dir); + if (exist_file (name) && (!mc_fhl_read_ini_file (fhl, name))) { + g_free (name); + return FALSE; + } + g_free (name); + + return TRUE; +} + +/* --------------------------------------------------------------------------------------------- */ + +gboolean +mc_fhl_parce_ini_file (mc_fhl_t * fhl) +{ + gchar **ftype_names, **orig_ftype_names; + gsize ftype_names_size; + + + mc_fhl_array_free (fhl); + fhl->filters = g_ptr_array_new (); + + if (!mc_config_has_group (fhl->config, "filehighlight")) + return FALSE; + + orig_ftype_names = ftype_names = + mc_config_get_keys (fhl->config, "filehighlight", &ftype_names_size); + + while (*ftype_names) { + + if (!mc_config_has_group (fhl->config, *ftype_names)) { + ftype_names++; + continue; + } + + if (mc_config_has_param (fhl->config, *ftype_names, "type")) { + /* parce filetype filter */ + mc_fhl_parce_get_file_type_id (fhl, *ftype_names); + } else if (mc_config_has_param (fhl->config, *ftype_names, "regexp")) { + /* parce regexp filter */ + mc_fhl_parce_get_regexp (fhl, *ftype_names); + } else if (mc_config_has_param (fhl->config, *ftype_names, "extensions")) { + /* parce extensions filter */ + mc_fhl_parce_get_extensions (fhl, *ftype_names); + } + + ftype_names++; + } + + g_strfreev (orig_ftype_names); + return TRUE; +} + +/* --------------------------------------------------------------------------------------------- */ diff --git a/src/filehighlight/internal.h b/src/filehighlight/internal.h new file mode 100644 index 000000000..4b66254cd --- /dev/null +++ b/src/filehighlight/internal.h @@ -0,0 +1,55 @@ +#ifndef MC__FILEHIGHLIGHT_INTERNAL_H +#define MC__FILEHIGHLIGHT_INTERNAL_H + +/*** typedefs(not structures) and defined constants **********************************************/ + +/*** enums ***************************************************************************************/ + +typedef enum { + MC_FLHGH_T_FTYPE, + MC_FLHGH_T_EXT, + MC_FLHGH_T_FREGEXP +} mc_flhgh_filter_type; + +typedef enum { + MC_FLHGH_FTYPE_T_FILE, + MC_FLHGH_FTYPE_T_FILE_EXE, + MC_FLHGH_FTYPE_T_DIR, + MC_FLHGH_FTYPE_T_LINK_DIR, + MC_FLHGH_FTYPE_T_LINK, + MC_FLHGH_FTYPE_T_HARDLINK, + MC_FLHGH_FTYPE_T_SYMLINK, + MC_FLHGH_FTYPE_T_STALE_LINK, + MC_FLHGH_FTYPE_T_DEVICE, + MC_FLHGH_FTYPE_T_DEVICE_BLOCK, + MC_FLHGH_FTYPE_T_DEVICE_CHAR, + MC_FLHGH_FTYPE_T_SPECIAL, + MC_FLHGH_FTYPE_T_SPECIAL_SOCKET, + MC_FLHGH_FTYPE_T_SPECIAL_FIFO, + MC_FLHGH_FTYPE_T_SPECIAL_DOOR, +} mc_flhgh_ftype_type; + +/*** structures declarations (and typedefs of structures)*****************************************/ + +typedef struct mc_fhl_filter_struct { + + int color_pair_index; + gchar *fgcolor; + gchar *bgcolor; + mc_flhgh_filter_type type; + mc_search_t *search_condition; + mc_flhgh_ftype_type file_type; + +} mc_fhl_filter_t; + +/*** global variables defined in .c file *********************************************************/ + +/*** declarations of public functions ************************************************************/ + + +void mc_fhl_array_free (mc_fhl_t *); + +gboolean mc_fhl_init_from_standart_files (mc_fhl_t *); + + +#endif diff --git a/src/main.c b/src/main.c index fa2ac1c25..300b51615 100644 --- a/src/main.c +++ b/src/main.c @@ -49,6 +49,7 @@ #include "../src/mcconfig/mcconfig.h" #include "../src/args.h" +#include "../src/filehighlight/fhl.h" #include "dir.h" #include "dialog.h" @@ -107,6 +108,8 @@ WPanel *left_panel = NULL; WPanel *right_panel = NULL; +mc_fhl_t *mc_filehighlight; + /* The pointer to the tree */ WTree *the_tree = NULL; @@ -1994,10 +1997,12 @@ main (int argc, char *argv[]) #endif /* HAVE_SUBSHELL_SUPPORT */ prompt = (geteuid () == 0) ? "# " : "$ "; + mc_filehighlight = mc_fhl_new (TRUE); /* Program main loop */ if (!midnight_shutdown) do_nc (); + mc_fhl_free (&mc_filehighlight); /* Save the tree store */ tree_store_save (); diff --git a/src/main.h b/src/main.h index aac3ec051..a74a013d4 100644 --- a/src/main.h +++ b/src/main.h @@ -104,6 +104,10 @@ extern const char *prompt; extern const char *edit_one_file; extern char *mc_home; extern char *mc_home_alt; + +struct mc_fhl_struct; +extern struct mc_fhl_struct *mc_filehighlight; + char *get_mc_lib_dir (void); void done_menu (void); diff --git a/src/screen.c b/src/screen.c index ab4a5e2c9..86d106c8d 100644 --- a/src/screen.c +++ b/src/screen.c @@ -37,6 +37,7 @@ #include "../src/tty/color.h" #include "../src/tty/mouse.h" /* For Gpm_Event */ #include "../src/tty/key.h" /* XCTRL and ALT macros */ +#include "../src/filehighlight/fhl.h" #include "dir.h" #include "panel.h" @@ -158,8 +159,10 @@ add_permission_string (char *dest, int width, file_entry *fe, int attr, int colo tty_setcolor (MARKED_SELECTED_COLOR); else tty_setcolor (MARKED_COLOR); - } else + } else if (color >= 0) tty_setcolor (color); + else + tty_lowlevel_setcolor (-color); tty_print_char (dest[i]); } @@ -470,37 +473,7 @@ file_compute_color (int attr, file_entry *fe) return (NORMAL_COLOR); } - /* if filetype_mode == true */ - if (S_ISDIR (fe->st.st_mode)) - return (DIRECTORY_COLOR); - else if (S_ISLNK (fe->st.st_mode)) { - if (fe->f.link_to_dir) - return (DIRECTORY_COLOR); - else if (fe->f.stale_link) - return (STALE_LINK_COLOR); - else - return (LINK_COLOR); - } else if (S_ISSOCK (fe->st.st_mode)) - return (SPECIAL_COLOR); - else if (S_ISCHR (fe->st.st_mode)) - return (DEVICE_COLOR); - else if (S_ISBLK (fe->st.st_mode)) - return (DEVICE_COLOR); - else if (S_ISNAM (fe->st.st_mode)) - return (DEVICE_COLOR); - else if (S_ISFIFO (fe->st.st_mode)) - return (SPECIAL_COLOR); - else if (S_ISDOOR (fe->st.st_mode)) - return (SPECIAL_COLOR); - else if (!S_ISREG (fe->st.st_mode)) - return (STALE_LINK_COLOR); /* non-regular file of unknown kind */ - else if (is_exe (fe->st.st_mode)) - return (EXECUTABLE_COLOR); - else if (fe->fname && (!strcmp (fe->fname, "core") - || !strcmp (extension (fe->fname), "core"))) - return (CORE_COLOR); - - return (NORMAL_COLOR); + return mc_fhl_get_color (mc_filehighlight, fe); } /* Formats the file number file_index of panel in the buffer dest */ @@ -551,7 +524,10 @@ format_file (char *dest, int limit, WPanel *panel, int file_index, int width, in perm = 2; } - tty_setcolor (color); + if (color >= 0) + tty_setcolor (color); + else + tty_lowlevel_setcolor (-color); preperad_text = (char*) str_fit_to_term(txt, len, format->just_mode); if (perm) diff --git a/src/tty/color-internal.c b/src/tty/color-internal.c index c4771980b..bef80250d 100644 --- a/src/tty/color-internal.c +++ b/src/tty/color-internal.c @@ -79,29 +79,20 @@ struct colorpair color_map [] = { { "gauge=", 0, 0 }, /* Color of the progress bar (percentage) *//* 21 */ { "input=", 0, 0 }, - /* Per file types colors */ - { "directory=", 0, 0 }, /* 23 */ - { "executable=", 0, 0 }, - { "link=", 0, 0 }, /* symbolic link (neither stale nor link to directory) */ - { "stalelink=", 0, 0 }, /* stale symbolic link */ - { "device=", 0, 0 }, - { "special=", 0, 0 }, /* sockets, fifo */ - { "core=", 0, 0 }, /* core files */ /* 29 */ - - { 0, 0, 0 }, /* not usable (DEFAULT_COLOR_INDEX) *//* 30 */ + { 0, 0, 0 }, /* not usable (DEFAULT_COLOR_INDEX) *//* 23 */ { 0, 0, 0 }, /* unused */ { 0, 0, 0 }, /* not usable (A_REVERSE) */ { 0, 0, 0 }, /* not usable (A_REVERSE_BOLD) */ - /* editor colors start at 34 */ - { "editnormal=", 0, 0 }, /* normal */ /* 34 */ + /* editor colors start at 27 */ + { "editnormal=", 0, 0 }, /* normal */ /* 27 */ { "editbold=", 0, 0 }, /* search->found */ { "editmarked=", 0, 0 }, /* marked/selected */ { "editwhitespace=", 0, 0 }, /* whitespace */ { "editlinestate=", 0, 0 }, /* line number bar*/ - /* error dialog colors start at 39 */ - { "errdhotnormal=", 0, 0 }, /* Error dialog normal/hot */ /* 38 */ + /* error dialog colors start at 32 */ + { "errdhotnormal=", 0, 0 }, /* Error dialog normal/hot */ /* 32 */ { "errdhotfocus=", 0, 0 }, /* Error dialog focused/hot */ }; diff --git a/src/tty/color-internal.h b/src/tty/color-internal.h index 75af00cdf..2b928c674 100644 --- a/src/tty/color-internal.h +++ b/src/tty/color-internal.h @@ -76,13 +76,6 @@ static const char default_colors[] = { "helpslink=yellow,blue:" "gauge=white,black:" "input=black,cyan:" - "directory=white,blue:" - "executable=brightgreen,blue:" - "link=lightgray,blue:" - "stalelink=brightred,blue:" - "device=brightmagenta,blue:" - "core=red,blue:" - "special=black,blue:" "editnormal=lightgray,blue:" "editbold=yellow,blue:" "editmarked=black,cyan:" diff --git a/src/tty/color.h b/src/tty/color.h index 5d49469fa..0788039e6 100644 --- a/src/tty/color.h +++ b/src/tty/color.h @@ -48,18 +48,8 @@ #define GAUGE_COLOR IF_COLOR (21, 0) #define INPUT_COLOR IF_COLOR (22, 0) -/* Add this to color panel, on BW all pairs are normal */ -#define DIRECTORY_COLOR IF_COLOR (23, 0) -#define EXECUTABLE_COLOR IF_COLOR (24, 0) -#define LINK_COLOR IF_COLOR (25, 0) -#define STALE_LINK_COLOR IF_COLOR (26, 0) -#define DEVICE_COLOR IF_COLOR (27, 0) -#define SPECIAL_COLOR IF_COLOR (28, 0) -#define CORE_COLOR IF_COLOR (29, 0) - - /* For the default color any unused index may be chosen. */ -#define DEFAULT_COLOR_INDEX 30 +#define DEFAULT_COLOR_INDEX 23 #define DEFAULT_COLOR IF_COLOR (DEFAULT_COLOR_INDEX, 0) /* @@ -67,18 +57,18 @@ * respectively * Last is defined to view color. */ -#define EDITOR_NORMAL_COLOR_INDEX 34 +#define EDITOR_NORMAL_COLOR_INDEX 27 #define EDITOR_NORMAL_COLOR IF_COLOR (EDITOR_NORMAL_COLOR_INDEX, 0) -#define EDITOR_BOLD_COLOR IF_COLOR (35, A_BOLD) -#define EDITOR_MARKED_COLOR IF_COLOR (36, A_REVERSE) -#define EDITOR_WHITESPACE_COLOR IF_COLOR (37, 0 /* irrelevant */) +#define EDITOR_BOLD_COLOR IF_COLOR (28, A_BOLD) +#define EDITOR_MARKED_COLOR IF_COLOR (29, A_REVERSE) +#define EDITOR_WHITESPACE_COLOR IF_COLOR (30, 0 /* irrelevant */) /* color of left 8 char status per line */ -#define LINE_STATE_COLOR IF_COLOR (38, 0) +#define LINE_STATE_COLOR IF_COLOR (31, 0) /* Error dialog colors */ -#define ERROR_HOT_NORMAL IF_COLOR (39, 0) -#define ERROR_HOT_FOCUS IF_COLOR (40, 0) +#define ERROR_HOT_NORMAL IF_COLOR (32, 0) +#define ERROR_HOT_FOCUS IF_COLOR (43, 0) void tty_init_colors (gboolean disable, gboolean force); void tty_colors_done (void);