Skip to content

Commit

Permalink
work on RGB colors. added DEFINE_COLOR command
Browse files Browse the repository at this point in the history
  • Loading branch information
andmarti1424 committed Mar 12, 2021
1 parent 05886db commit 45326a5
Show file tree
Hide file tree
Showing 7 changed files with 331 additions and 86 deletions.
249 changes: 214 additions & 35 deletions src/color.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@
* @file color.c
* @author Andrés Martinelli <[email protected]>
* @date 2017-07-18
* @brief TODO Write a brief file description.
* @brief File containing color functions
*
* TODO Write a longer file description here.
*/

#include <sys/types.h>
Expand All @@ -68,6 +67,7 @@ struct dictionary * get_d_colors_param() {
return d_colors_param;
}

static struct custom_color * custom_colors = NULL;
/**
* @brief Generate DEFAULT 'initcolor' colors
*
Expand Down Expand Up @@ -97,15 +97,16 @@ void start_default_ucolors() {
// Set some colors attributes
ucolors[ DEFAULT ].fg = WHITE;
ucolors[ DEFAULT ].bg = DEFAULT_COLOR;
ucolors[ HEADINGS ].fg = WHITE;
ucolors[ HEADINGS ].bg = RED;
ucolors[ HEADINGS ].fg = RED;
ucolors[ HEADINGS ].bg = WHITE;
ucolors[ WELCOME ].fg = WHITE;
ucolors[ WELCOME ].bg = DEFAULT_COLOR;
ucolors[ WELCOME ].bold = 1;
ucolors[ CELL_SELECTION ].fg = BLUE; // cell selection in headings
ucolors[ CELL_SELECTION ].bg = WHITE;
ucolors[ CELL_SELECTION_SC ].fg = BLACK; // cell selection in spreadsheet
ucolors[ CELL_SELECTION_SC ].bg = WHITE;
ucolors[ CELL_SELECTION ].bg = BLUE; // cell selection in headings
ucolors[ CELL_SELECTION ].fg = WHITE;
ucolors[ CELL_SELECTION ].bold = 1;
ucolors[ CELL_SELECTION_SC ].fg = DEFAULT_COLOR; // cell selection in spreadsheet
ucolors[ CELL_SELECTION_SC ].bg = BLUE;
ucolors[ NUMB ].fg = CYAN;
ucolors[ NUMB ].bg = DEFAULT_COLOR;
ucolors[ STRG ].fg = BLUE;
Expand All @@ -124,10 +125,10 @@ void start_default_ucolors() {
ucolors[ MODE ].fg = WHITE;
ucolors[ MODE ].bg = DEFAULT_COLOR;
ucolors[ MODE ].bold = 1;
ucolors[ CELL_ID ].fg = RED;
ucolors[ CELL_ID ].bg = DEFAULT_COLOR;
ucolors[ CELL_ID ].fg = WHITE;
ucolors[ CELL_ID ].bg = BLACK;
ucolors[ CELL_ID ].bold = 1;
ucolors[ CELL_FORMAT ].fg = CYAN;
ucolors[ CELL_FORMAT ].fg = RED;
ucolors[ CELL_FORMAT ].bg = DEFAULT_COLOR;
ucolors[ CELL_CONTENT ].fg = CYAN;
ucolors[ CELL_CONTENT ].bg = DEFAULT_COLOR;
Expand All @@ -146,7 +147,7 @@ void start_default_ucolors() {
}

/**
* @brief TODO <brief function description>
* @brief Create a dictionary that stores correspondence between macros and key values
*
* Create a dictionary that stores the correspondence between macros and key
* values (integers) defined in '.sc' files or through the color command.
Expand All @@ -159,6 +160,7 @@ void start_default_ucolors() {
*/

void set_colors_param_dict() {

d_colors_param = create_dictionary();
char str[3];
str[0]='\0';
Expand Down Expand Up @@ -222,9 +224,9 @@ void set_colors_param_dict() {
}

/**
* @brief TODO <brief function description>
* @brief free the colors parameters dictionary
*
* TODO Write longer function description.
* Free the colors parameters dictionary
*
* Example usage:
* @code
Expand All @@ -239,7 +241,7 @@ void free_colors_param_dict() {
}

/**
* @brief TODO <brief function description>
* @brief Function that colorize the different types shown on screen
*
* Change color definition with user's one STR: color definition from '.sc'
* file. It can be obtained at run time with the ':color str' command.
Expand Down Expand Up @@ -275,22 +277,41 @@ void chg_color(char * str) {
}

// Validate the values for those keys are correct
if (
(get(d_colors_param, get(d, "type")) == NULL) ||
(get(d_colors_param, get(d, "fg")) == NULL) ||
(get(d_colors_param, get(d, "bg")) == NULL) ||
(atoi(get(d_colors_param, get(d, "fg"))) > WHITE) ||
(atoi(get(d_colors_param, get(d, "bg"))) > WHITE)
) {
sc_error("One of the values specified is wrong. Please check the values of type, fg and bg.");
// bg, fg should have valid values BLACK(0) to WHITE(7) for ncurses stock colors
// or a custom color name, or -1, indicating default TERMINAL color
if (get(d_colors_param, get(d, "type")) == NULL) {
sc_error("Error setting color. Invalid type value.");
destroy_dictionary(d);
return;
}

if (get(d_colors_param, get(d, "fg")) == NULL && get_custom_color(get(d, "fg")) == NULL) {
sc_error("Error setting color. Invalid fg value. It is not and ncurses color nor user defined color.");
destroy_dictionary(d);
return;
}

if (get(d_colors_param, get(d, "bg")) == NULL && get_custom_color(get(d, "bg")) == NULL) {
sc_error("Error setting color. Invalid bg value. It is not and ncurses color nor user defined color.");
destroy_dictionary(d);
return;
}

// Change the color
int type = atoi(get(d_colors_param, get(d, "type")));
ucolors[ type ].fg = atoi(get(d_colors_param, get(d, "fg")));
ucolors[ type ].bg = atoi(get(d_colors_param, get(d, "bg")));
struct custom_color * cc;
if ((cc = get_custom_color(get(d, "bg"))) != NULL) { // bg is custom color
ucolors[ type ].bg = 7 + cc->number;
} else { // bg is stock ncurses color
ucolors[ type ].bg = atoi(get(d_colors_param, get(d, "bg")));
}

if ((cc = get_custom_color(get(d, "fg"))) != NULL) { // fg is custom color
ucolors[ type ].fg = 7 + cc->number;
} else { // fg is stock ncurses color
ucolors[ type ].fg = atoi(get(d_colors_param, get(d, "fg")));
}

if (((cl = get(d, "bold")) != NULL) && cl[0] != '\0') ucolors[ type ].bold = atoi(get(d, "bold"));
if (((cl = get(d, "italic")) != NULL) && cl[0] != '\0') ucolors[ type ].italic = atoi(get(d, "italic"));
if (((cl = get(d, "dim")) != NULL) && cl[0] != '\0') ucolors[ type ].dim = atoi(get(d, "dim"));
Expand Down Expand Up @@ -344,8 +365,9 @@ void color_cell(int r, int c, int rf, int cf, char * str) {

// Validations
if (
((cl = get(d, "fg")) != NULL && cl[0] != '\0' && get(d_colors_param, get(d, "fg")) == NULL) ||
((cl = get(d, "bg")) != NULL && cl[0] != '\0' && get(d_colors_param, get(d, "bg")) == NULL)) {
((cl = get(d, "fg")) != NULL && cl[0] != '\0' && get(d_colors_param, get(d, "fg")) == NULL && get_custom_color(cl) == NULL) ||
((cl = get(d, "bg")) != NULL && cl[0] != '\0' && get(d_colors_param, get(d, "bg")) == NULL && get_custom_color(cl) == NULL)
) {
sc_error("One of the values specified is wrong. Please check the values of type, fg and bg.");
destroy_dictionary(d);
return;
Expand Down Expand Up @@ -382,11 +404,27 @@ void color_cell(int r, int c, int rf, int cf, char * str) {
n->ucolor->blink = 0;
}

if ((cl = get(d, "bg")) != NULL && cl[0] != '\0')
n->ucolor->bg = atoi(get(d_colors_param, get(d, "bg")));

if ((cl = get(d, "fg")) != NULL && cl[0] != '\0')
n->ucolor->fg = atoi(get(d_colors_param, get(d, "fg")));
struct custom_color * cc;
if ((cl = get(d, "bg")) != NULL && cl[0] != '\0') {
if (get(d_colors_param, get(d, "bg")) != NULL) {
n->ucolor->bg = atoi(get(d_colors_param, get(d, "bg")));
} else if ((cc = get_custom_color(get(d, "bg"))) != NULL) {
n->ucolor->bg = 7 + cc->number;
} else {
sc_error("error setting bg color. we should not be here.");
n->ucolor->bg = DEFAULT_COLOR;
}
}
if ((cl = get(d, "fg")) != NULL && cl[0] != '\0') {
if (get(d_colors_param, get(d, "fg")) != NULL) {
n->ucolor->fg = atoi(get(d_colors_param, get(d, "fg")));
} else if ((cc = get_custom_color(get(d, "fg"))) != NULL) {
n->ucolor->fg = 7 + cc->number;
} else {
sc_error("error setting fg color. we should not be here.");
n->ucolor->fg = DEFAULT_COLOR;
}
}

if ((cl = get(d, "bold")) != NULL && cl[0] != '\0') n->ucolor->bold = atoi(get(d, "bold"));
if ((cl = get(d, "italic")) != NULL && cl[0] != '\0') n->ucolor->italic = atoi(get(d, "italic"));
Expand Down Expand Up @@ -501,13 +539,14 @@ int same_ucolor(struct ucolor * u, struct ucolor * v) {
}

/**
* @brief TODO <brief function description>
* @brief Redefine one of the 8 ncurses colors to a new RGB value.
*
* TODO Write longer function description.
* Redefine stock ncurses color to a new RGB value. Only if terminal supports it.
* RGB values must be between 0 and 1000.
*
* Example usage:
* @code
* redefine_color(<color>,<var1>,<var2>,<var3>);
* redefine_color(<color>,<r>,<g>,<b>);
* @endcode
* returns: 0 on success, -1 on error
*/
Expand All @@ -534,3 +573,143 @@ int redefine_color(char * color, int r, int g, int b) {
#endif
return -1;
}

/**
* @brief Define a custom color
*
* Define a custom color. If terminal does not support 256 colors, return.
*
* Example usage:
* @code
* define_color(<color>,<r>,<g>,<b>);
* @endcode
* returns: 0 on success, -1 on error
*/
int define_color(char * color, int r, int g, int b) {

#if defined(NCURSES) && defined(USECOLORS)
if (atoi(get_conf_value("nocurses"))) {
sc_error("Could not define color %s. Not using NCURSES.", color);
return -1;
} else if (! has_colors () || ! can_change_color() || COLORS < 9) {
sc_error("Could not define color %s. Not supported by terminal.", color);
return -1;
} else if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) {
sc_error("Could not define color %s. One of the RGB values is invalid.", color);
return -1;
}

int number_defined_colors;
struct custom_color * cc;

// update color value if it already exists
if ((cc = get_custom_color(color)) != NULL) {
sc_debug("Color '%s' already defined. Updating its RGB values.", color);
} else if ((number_defined_colors = count_custom_colors()) == 24) {
sc_error("Could not define color %s. There are already 24 custom colors defined.", color);
return -1;
} else { // we create a new custom color
cc = malloc (sizeof(struct custom_color));
cc->number = number_defined_colors+1;
cc->name = (char *) malloc (sizeof(char) * (strlen(color) + 1));
strcpy(cc->name, color);
cc->p_next = custom_colors;
custom_colors = cc;
}
cc->r = r;
cc->g = g;
cc->b = b;
//sc_debug("modified extended color: %d", 7 + cc->number);
init_extended_color(7 + cc->number, RGB(r, g, b));

if (! loading) sc_info("Defined custom color #%d with name '%s' and RGB values %d %d %d", cc->number, cc->name, cc->r, cc->g, cc->b);
return 0;
#endif
sc_error("Could not define color %s", color);
return -1;
}

/**
* @brief Free memory of custom_colors
*
* Free custom_colors memory
*
* Example usage:
* @code
* free_custom_colors();
* @endcode
* returns 0
*/
int free_custom_colors() {
struct custom_color * aux;
while (custom_colors != NULL) {
aux = custom_colors->p_next;
free(custom_colors->name);
free(custom_colors);
custom_colors = aux;
}
return 0;
}

/**
* @brief get custom color by name
*
* get custom color by name
*
* Example usage:
* @code
get_custom_color("skyblue")
* @endcode
* returns struct custom_color * if found
* returns NULL otherwise
*/
struct custom_color * get_custom_color(char * name) {
struct custom_color * aux = custom_colors;
while (aux != NULL) {
if (! strcasecmp(name, aux->name)) return aux;
aux=aux->p_next;
}
return NULL;
}

/**
* @brief count the defined custom colors
*
* count the defined custom colors
*
* Example usage:
* @code
count_custom_colors()
* @endcode
* returns int
*/
int count_custom_colors() {
int c = 0;
struct custom_color * aux = custom_colors;
while (aux != NULL) {
aux=aux->p_next;
c++;
}
return c;
}

/**
* @brief get custom color by number
*
* get custom color by number
*
* Example usage:
* @code
get_custom_color_by_number(2)
* @endcode
* returns struct custom_color * if found
* returns NULL otherwise
*/
struct custom_color * get_custom_color_by_number(int number) {
struct custom_color * aux = custom_colors;
while (aux != NULL) {
if (number == aux->number) return aux;
aux=aux->p_next;
}
return NULL;
}
27 changes: 27 additions & 0 deletions src/color.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@

#include "macros.h"

#include <math.h>
#define RGB(r, g, b) floor(r*999/255), floor(g*999/255), floor(b*999/255)

#define N_INIT_PAIRS 19

struct ucolor {
Expand All @@ -58,6 +61,24 @@ struct ucolor {
int blink;
};

struct custom_color {
int number; // this is the custom color number. since we max have 24 user custom colors.
char * name;
int r;
int g;
int b;

/* TODO we actually could store rgb values in just one int
int rgb = ((r & 0x0ff) << 16) | ((g & 0x0ff) << 8) | (b & 0x0ff);
int red = (rgb >> 16) & 0x0ff;
int green = (rgb >> 8) & 0x0ff;
int blue = (rgb) & 0x0ff;
*/

struct custom_color * p_next;
};


extern struct ucolor ucolors[N_INIT_PAIRS];

struct dictionary * get_d_colors_param();
Expand All @@ -69,3 +90,9 @@ void free_colors_param_dict();
void chg_color(char * str);
int same_ucolor(struct ucolor * u, struct ucolor * v);
int redefine_color(char * color, int r, int g, int b);

int define_color(char * color, int r, int g, int b);
int free_custom_colors();
struct custom_color * get_custom_color(char * name);
int count_custom_colors();
struct custom_color * get_custom_color_by_number(int number);
Loading

0 comments on commit 45326a5

Please sign in to comment.