#include "os.h"
#include "display.h"
#include "message.h"
#include "color.h"
#include "utils.h"
typedef struct color_entry {
char *tag;
int min;
int max;
char color;
struct color_entry *next;
struct color_entry *tagnext;
} color_entry;
static color_entry *entries = NULL;
static color_entry **bytag = NULL;
static char **bytag_names = NULL;
static int totaltags = 0;
static int tagcnt = 0;
static int color_off = 0;
static char **color_ansi = NULL;
static int num_color_ansi = 0;
static int max_color_ansi = 0;
static int
color_slot(char *str)
{
int i;
for (i = 0; i < num_color_ansi; i++)
{
if (strcmp(color_ansi[i], str) == 0)
{
return i;
}
}
if (num_color_ansi >= max_color_ansi)
{
max_color_ansi += COLOR_ANSI_SLOTS;
color_ansi = (char **)realloc(color_ansi, max_color_ansi * sizeof(char *));
}
color_ansi[num_color_ansi] = strdup(str);
return num_color_ansi++;
}
int
color_env_parse(char *env)
{
char *p;
char *min;
char *max;
char *str;
int len;
color_entry *ce;
color_ansi = (char **)malloc(COLOR_ANSI_SLOTS * sizeof(char *));
max_color_ansi = COLOR_ANSI_SLOTS;
color_slot("0");
if (env != NULL)
{
p = strtok(env, ":");
while (p != NULL)
{
if ((min = strchr(p, '=')) != NULL &&
(max = strchr(min, ',')) != NULL &&
(str = strchr(max, '#')) != NULL)
{
ce = (color_entry *)malloc(sizeof(color_entry));
len = min - p;
ce->tag = (char *)malloc(len + 1);
strncpy(ce->tag, p, len);
ce->tag[len] = '\0';
ce->min = atoi(++min);
ce->max = atoi(++max);
ce->color = color_slot(++str);
ce->next = entries;
entries = ce;
}
else
{
if (min != NULL)
{
len = min - p;
}
else
{
len = strlen(p);
}
message_error(" %.*s: bad color entry", len, p);
}
p = strtok(NULL, ":");
}
}
return 0;
}
int
color_tag(char *tag)
{
color_entry *entryp;
color_entry *tp;
if (tag == NULL || *tag == '\0')
{
return -1;
}
dprintf("color_tag(%s)\n", tag);
if (bytag == NULL)
{
totaltags = 10;
bytag = (color_entry **)malloc(totaltags * sizeof(color_entry *));
bytag_names = (char **)malloc(totaltags * sizeof(char *));
}
if (tagcnt >= totaltags)
{
totaltags *= 2;
bytag = (color_entry **)realloc(bytag, totaltags * sizeof(color_entry *));
bytag_names = (char **)realloc(bytag_names, totaltags * sizeof(char *));
}
entryp = entries;
tp = NULL;
while (entryp != NULL)
{
if (strcmp(entryp->tag, tag) == 0)
{
entryp->tagnext = tp;
tp = entryp;
}
entryp = entryp->next;
}
bytag[tagcnt] = tp;
bytag_names[tagcnt] = strdup(tag);
dprintf("color_tag: returns %d\n", tagcnt);
return (tagcnt++);
}
int
color_test(int tagidx, int value)
{
color_entry *ce;
if (tagidx < 0 || tagidx >= tagcnt || color_off)
{
return 0;
}
ce = bytag[tagidx];
while (ce != NULL)
{
if ((!ce->min || ce->min <= value) &&
(!ce->max || ce->max >= value))
{
return ce->color;
}
ce = ce->tagnext;
}
return 0;
}
char *
color_setstr(int color)
{
static char v[32];
v[0] = '\0';
if (color >= 0 && color < num_color_ansi)
{
snprintf(v, sizeof(v), "\033[%sm", color_ansi[color]);
}
return v;
}
void
color_dump(FILE *f)
{
color_entry *ep;
int i;
int col;
int len;
fputs("These color tags are available:", f);
col = 81;
for (i = 0; i < tagcnt; i++)
{
len = strlen(bytag_names[i]) + 1;
if (len + col > 79)
{
fputs("\n ", f);
col = 2;
}
fprintf(f, " %s", bytag_names[i]);
col += len;
}
fputs("\n\nTop color settings:\n", f);
for (i = 0; i < tagcnt; i++)
{
ep = bytag[i];
while (ep != NULL)
{
fprintf(f, " %s (%d-", ep->tag, ep->min);
if (ep->max != 0)
{
fprintf(f, "%d", ep->max);
}
fprintf(f, "): ansi color %s, %sSample Text",
color_ansi[(int)ep->color],
color_setstr(ep->color));
fprintf(f, "%s\n", color_setstr(0));
ep = ep -> tagnext;
}
}
}
void
color_debug(FILE *f)
{
color_entry *ep;
int i;
fprintf(f, "color debug dump\n");
ep = entries;
while (ep != NULL)
{
fprintf(f, "%s(%d,%d): slot %d, ansi %s, %sSample Text",
ep->tag, ep->min, ep->max, ep->color, color_ansi[(int)ep->color],
color_setstr(ep->color));
fprintf(f, "%s\n", color_setstr(0));
ep = ep -> next;
}
fprintf(f, "\ntags:");
for (i = 0; i < tagcnt; i++)
{
fprintf(f, " %s", bytag_names[i]);
}
fprintf(f, "\n");
}
int
color_activate(int i)
{
if (i == -1)
{
color_off = !color_off;
}
else
{
color_off = !i;
}
return color_off;
}