Changeset View
Changeset View
Standalone View
Standalone View
contrib/top/color.c
Property | Old Value | New Value |
---|---|---|
svn:eol-style | null | native \ No newline at end of property |
svn:keywords | null | FreeBSD=%H \ No newline at end of property |
svn:mime-type | null | text/plain \ No newline at end of property |
/* | |||||
* Copyright (c) 1984 through 2008, William LeFebvre | |||||
* All rights reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions are met: | |||||
* | |||||
* * Redistributions of source code must retain the above copyright | |||||
* notice, this list of conditions and the following disclaimer. | |||||
* | |||||
* * Redistributions in binary form must reproduce the above | |||||
* copyright notice, this list of conditions and the following disclaimer | |||||
* in the documentation and/or other materials provided with the | |||||
* distribution. | |||||
* | |||||
* * Neither the name of William LeFebvre nor the names of other | |||||
* contributors may be used to endorse or promote products derived from | |||||
* this software without specific prior written permission. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
*/ | |||||
/* | |||||
* Top users/processes display for Unix | |||||
* Version 3 | |||||
*/ | |||||
/* | |||||
* This file handles color definitions and access for augmenting | |||||
* the output with ansi color sequences. | |||||
* | |||||
* The definition of a color setting is as follows, separated by | |||||
* colons: | |||||
* | |||||
* tag=minimum,maximum#code | |||||
* | |||||
* "tag" is the name of the value to display with color. | |||||
* | |||||
* "minimum" and "maximum" are positive integer values defining a range: | |||||
* when the value is within this range it will be shown with the | |||||
* specified color. A missing value indicates that no check should be | |||||
* made (i.e.: ",25" is n <= 25; "25,50" is 25 <= n <= 50; and "50," | |||||
* is 50 <= n). | |||||
* | |||||
* "code" is the ansi sequence that defines the color to use with the | |||||
* escape sequence "[m". Semi-colons are allowed in this string to | |||||
* combine attributes. | |||||
*/ | |||||
#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; | |||||
} | |||||
} | |||||
/* need a new slot */ | |||||
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) | |||||
* | |||||
* Parse a color specification "env" (such as one found in the environment) and | |||||
* add them to the list of entries. Always returns 0. Should only be called | |||||
* once. | |||||
*/ | |||||
int | |||||
color_env_parse(char *env) | |||||
{ | |||||
char *p; | |||||
char *min; | |||||
char *max; | |||||
char *str; | |||||
int len; | |||||
color_entry *ce; | |||||
/* initialization */ | |||||
color_ansi = (char **)malloc(COLOR_ANSI_SLOTS * sizeof(char *)); | |||||
max_color_ansi = COLOR_ANSI_SLOTS; | |||||
/* color slot 0 is always "0" */ | |||||
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) | |||||
* | |||||
* Declare "tag" as a color tag. Return a tag index to use when testing | |||||
* a value against the tests for this tag. Should not be called before | |||||
* color_env_parse. | |||||
*/ | |||||
int | |||||
color_tag(char *tag) | |||||
{ | |||||
color_entry *entryp; | |||||
color_entry *tp; | |||||
/* check for absurd arguments */ | |||||
if (tag == NULL || *tag == '\0') | |||||
{ | |||||
return -1; | |||||
} | |||||
dprintf("color_tag(%s)\n", tag); | |||||
/* initial allocation */ | |||||
if (bytag == NULL) | |||||
{ | |||||
totaltags = 10; | |||||
bytag = (color_entry **)malloc(totaltags * sizeof(color_entry *)); | |||||
bytag_names = (char **)malloc(totaltags * sizeof(char *)); | |||||
} | |||||
/* if we dont have enough room then reallocate */ | |||||
if (tagcnt >= totaltags) | |||||
{ | |||||
totaltags *= 2; | |||||
bytag = (color_entry **)realloc(bytag, totaltags * sizeof(color_entry *)); | |||||
bytag_names = (char **)realloc(bytag_names, totaltags * sizeof(char *)); | |||||
} | |||||
/* initialize scan */ | |||||
entryp = entries; | |||||
tp = NULL; | |||||
/* look for tag in the list of entries */ | |||||
while (entryp != NULL) | |||||
{ | |||||
if (strcmp(entryp->tag, tag) == 0) | |||||
{ | |||||
entryp->tagnext = tp; | |||||
tp = entryp; | |||||
} | |||||
entryp = entryp->next; | |||||
} | |||||
/* we track names in the array bytag */ | |||||
bytag[tagcnt] = tp; | |||||
bytag_names[tagcnt] = strdup(tag); | |||||
/* return this index number as a reference */ | |||||
dprintf("color_tag: returns %d\n", tagcnt); | |||||
return (tagcnt++); | |||||
} | |||||
/* | |||||
* int color_test(int tagidx, int value) | |||||
* | |||||
* Test "value" against tests for tag "tagidx", a number previously returned | |||||
* by color_tag. Return the correct color number to use when highlighting. | |||||
* If there is no match, return 0 (color 0). | |||||
*/ | |||||
int | |||||
color_test(int tagidx, int value) | |||||
{ | |||||
color_entry *ce; | |||||
/* sanity check */ | |||||
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) | |||||
* | |||||
* Return ANSI string to set the terminal for color number "color". | |||||
*/ | |||||
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; | |||||
} |