dstyle.cc

来自「Click is a modular router toolkit. To us」· CC 代码 · 共 2,157 行 · 第 1/4 页

CC
2,157
字号
#ifdef HAVE_CONFIG_H# include <config.h>#endif#include <click/config.h>#include "dstyle.hh"#include "dwidget.hh"#include "wdiagram.hh"#include "hvalues.hh"#include <click/userutils.hh>#include <click/confparse.hh>#include <click/straccum.hh>#include <click/bitvector.hh>#include <clicktool/processingt.hh>#include <clicktool/elementmap.hh>#include <list>#include <math.h>#include <string.h>#include "crouter.hh"#include "whandler.hh"extern "C" {#include "support.h"}namespace clicky {struct colordef {    const char *name;    int length;    uint32_t value;};static const colordef colordefs[] = {    { "aqua", 4, 0x00FFFF },    { "black", 5, 0x000000 },    { "blue", 4, 0x0000FF },    { "fuchsia", 7, 0xFF00FF },    { "gray", 4, 0x808080 },    { "green", 5, 0x008000 },    { "lime", 4, 0x00FF00 },    { "maroon", 6, 0x800000 },    { "navy", 4, 0x000080 },    { "none", 4, 0xFF000000 },    { "olive", 5, 0x808000 },    { "orange", 6, 0xFFA500 },    { "purple", 6, 0x800080 },    { "red", 3, 0xFF0000 },    { "silver", 6, 0xC0C0C0 },    { "teal", 4, 0x008080 },    { "white", 5, 0xFFFFFF },    { "yellow", 6, 0xFFFF00 }};const double white_color[4] = { 1, 1, 1, 1 };const char default_css[] = "port.input {\n\    port-shape: triangle;\n\    port-length: 11px;\n\    port-width: 7px;\n\    port-margin: 1px;\n\    port-edge-padding: 2px;\n\}\n\port.output {\n\    port-shape: rectangle;\n\    port-length: 9px;\n\    port-width: 5.5px;\n\    port-margin: 1px;\n\    port-edge-padding: 2px;\n\}\n\port.push, port.push.agnostic {\n\    port-color: black;\n\}\n\port.pull, port.pull.agnostic {\n\    port-color: white;\n\}\n\port.agnostic {\n\    port-color: gray;\n\}\n\port.push, port.pull {\n\    port-border: black 1px solid;\n\}\n\port.agnostic, port.push.agnostic, port.pull.agnostic {\n\    port-border: black 1px inset;\n\}\n\port.push.error, port.push.agnostic.error {\n\    port-color: red;\n\}\n\port.pull.error, port.pull.agnostic.error {\n\    port-color: rgb(100%, 75%, 75%);\n\}\n\port.push.error, port.pull.error {\n\    port-border: red 1px solid;\n\}\n\port.agnostic.error, port.push.agnostic.error, port.pull.agnostic.error {\n\    port-border: red 1px inset;\n\}\n\* {\n\    background: rgb(100%, 100%, 87%);\n\    color: black;\n\    border: 1px solid black;\n\    padding: 8px 12px;\n\    margin: 20px 14px;\n\    shadow: drop rgba(50%, 50%, 45%, 50%) 3px;\n\    orientation: vertical;\n\    /* min-height: 30px; */\n\    /* height-step: 4px; */\n\    scale: 100%;\n\    queue-stripe: 1px solid rgb(87%, 87%, 50%);\n\    queue-stripe-spacing: 12px;\n\    text: \"%n\\n<small>%c</small>\";\n\    display: open;\n\    port-display: both;\n\    port-font: 6;\n\    @media print {\n\	font: Times;\n\	port-font: Times 6;\n\    }\n\    /* @media screen { font: URW Palladio L italic 20; } */\n\}\n\*.anonymous {\n\    text: \"%n\";\n\}\n\* * {\n\    background: rgb(98%, 98%, 81%);\n\}\n\* * * {\n\    background: rgb(96%, 96%, 75%);\n\}\n\* * * * {\n\    background: rgb(94%, 94%, 69%);\n\}\n\@media screen {\n\*:hover {\n\    background: #fffff2;\n\}\n\*:active, *:active:hover {\n\    background: #ffff94;\n\    shadow: unscaled-outline rgba(90%, 20%, 95%, 50%) 3px;\n\}\n\*:pressed, *:active:pressed {\n\    shadow: drop rgba(50%, 50%, 45%, 50%) 3px;\n\}\n\}\n\*Queue {\n\    min-length: 49.6px;\n\    style: queue;\n\}\n\fullness {\n\    style: fullness;\n\    length: length;\n\    capacity: capacity;\n\    color: rgba(0%, 0%, 100%, 20%);\n\    autorefresh: length 0.1s;\n\}\n\activity {\n\    style: activity;\n\    handler: count;\n\    decay: 5s;\n\    max-value: 3;\n\    type: rate;\n\    autorefresh: 1s;\n\}";/***** * property definitions */static PermString::Initializer permstring_initializer;static HashTable<PermString, int> property_map;static dcss_propmatch port_pm[] = {    { "port-shape", 0 },    { "port-length", 0 },    { "port-width", 0 },    { "port-color", 0 },    { "port-border-style", 0 },    { "port-border-width", 0 },    { "port-border-color", 0 },    { "port-margin-top", 0 },    { "port-margin-right", 0 },    { "port-margin-bottom", 0 },    { "port-margin-left", 0 },    { "port-edge-padding", 0 },    { "port-display", 0 },    { "port-text", 0 },    { "port-font", 0 }};static dcss_propmatch elt_pm[] = {    { "color", 0 },    { "background-color", 0 },    { "border-style", 0 },    { "border-color", 0 },    { "shadow-style", 0 },    { "shadow-width", 0 },    { "shadow-color", 0 },    { "style", 0 },    { "text", 0 },    { "display", 0 },    { "font", 0 },    { "decorations", 0 },    { "queue-stripe-style", 0 },    { "queue-stripe-width", 0 },    { "queue-stripe-color", 0 },    { "port-split", 0 },    { "flow-split", 0 }};static dcss_propmatch elt_size_pm[] = {    { "border-width", 0 },    { "padding-top", 0 },    { "padding-right", 0 },    { "padding-bottom", 0 },    { "padding-left", 0 },    { "min-width", 0 },    { "min-height", 0 },    { "height-step", 0 },    { "margin-top", 0 },    { "margin-right", 0 },    { "margin-bottom", 0 },    { "margin-left", 0 },    { "queue-stripe-spacing", 0 },    { "scale", 0 },    { "orientation", 0 },    { "min-length", 0 }};static dcss_propmatch handler_pm[] = {    { "autorefresh", 0 },    { "autorefresh-period", 0 },    { "display", 0 },    { "allow-refresh", 0 }};static dcss_propmatch fullness_pm[] = {    { "length", 0 },    { "capacity", 0 },    { "color", 0 },    { "autorefresh", 0 },    { "autorefresh-period", 0 }};static dcss_propmatch activity_pm[] = {    { "handler", 0 },    { "color", 0 },    { "autorefresh", 0 },    { "autorefresh-period", 0 },    { "type", 0 },    { "max-value", 0 },    { "min-value", 0 },    { "decay", 0 }};enum {    num_port_pm = sizeof(port_pm) / sizeof(port_pm[0]),    pflag_port = 1,    num_elt_pm = sizeof(elt_pm) / sizeof(elt_pm[0]),    pflag_elt = 2,    num_elt_size_pm = sizeof(elt_size_pm) / sizeof(elt_size_pm[0]),    pflag_elt_size = 4,    num_handler_pm = sizeof(handler_pm) / sizeof(handler_pm[0]),    pflag_handler = 8,    num_fullness_pm = sizeof(fullness_pm) / sizeof(fullness_pm[0]),    pflag_fullness = 16,    num_activity_pm = sizeof(activity_pm) / sizeof(activity_pm[0]),    pflag_activity = 32,    pflag_no_below = 64};/***** * */bool cp_pixel(const String &str, double *v){    double scale = 1;    const char *s = str.begin(), *send = str.end();    if (s + 2 < send) {	if (send[-2] == 'p' && send[-1] == 'x')	    send -= 2;	else if (send[-2] == 'i' && send[-1] == 'n')	    scale = 96, send -= 2;	else if (send[-2] == 'c' && send[-1] == 'm')	    scale = 96.0 / 2.54, send -= 2;	else if (send[-2] == 'm' && send[-1] == 'm')	    scale = 96.0 / 25.4, send -= 2;	else if (send[-2] == 'p' && send[-1] == 't')	    scale = 96.0 / 72.0, send -= 2;	else if (send[-2] == 'p' && send[-1] == 'c')	    scale = 96.0 / 6.0, send -= 2;	/* XXX em, ex? */    }    double value;    if (cp_double(str.substring(s, send), &value)) {	*v = value * scale;	return true;    } else	return false;}bool cp_relative(const String &str, double *v){    if (str && str.back() == '%' && cp_double(str.substring(0, -1), v)) {	*v /= 100;	return true;    } else	return cp_double(str, v);}bool cp_color(const String &str, double *r, double *g, double *b, double *a){    const char *s = str.begin(), *send = str.end();    if (s == send || (s[0] == '#' && s + 4 != send && s + 7 != send))	return false;    // hex specification?    if (s[0] == '#') {	uint32_t v = 0;	for (++s; s != send; ++s)	    if (*s >= '0' && *s <= '9')		v = (v << 4) + *s - '0';	    else if (*s >= 'A' && *s <= 'F')		v = (v << 4) + *s - 'A' + 10;	    else if (*s >= 'a' && *s <= 'f')		v = (v << 4) + *s - 'a' + 10;	    else		return false;	if (str.length() == 4) {	    *r = (v >> 8) / 15.;	    *g = ((v >> 4) & 0xF) / 15.;	    *b = (v & 0xF) / 15.;	    if (a)		*a = 1;	    return true;	} else {	    *r = (v >> 16) / 255.;	    *g = ((v >> 8) & 0xFF) / 255.;	    *b = (v & 0xFF) / 255.;	    if (a)		*a = 1;	    return true;	}    }    // rgb specification?    if (s + 5 < send && (memcmp(s, "rgb(", 4) == 0			 || memcmp(s, "rgba(", 5) == 0)) {	double x[4];	if (s[3] == 'a')	    ++s;	s += 4;	x[3] = 1;	for (int i = 0; i < 4; ++i) {	    s = cp_skip_comment_space(s, send);	    const char *n = s;	    while (s != send && (isdigit((unsigned char) *s) || *s == '.'				 || *s == '+' || *s == '-'))		++s;	    if (s == send || n == s)		return false;	    x[i] = strtod(n, 0);	    if (*s == '%') {		x[i] /= 100.;		++s;	    } else if (i < 3)		x[i] /= 255.;	    if (x[i] < 0)		x[i] = 0;	    else if (x[i] > 1)		x[i] = 1;	    if (i < 3) {		if (s != send && *s != ',')		    s = cp_skip_comment_space(s, send);		if (s != send && *s == ')' && i >= 2)		    break;		else if (s != send && *s == ',')		    ++s;		else if (s != send)		    return false;	    }	}	s = cp_skip_comment_space(s, send);	if (s + 1 != send || s[0] != ')')	    return false;	*r = x[0];	*g = x[1];	*b = x[2];	if (a)	    *a = x[3];	return true;    }    // color name?    const colordef *cl = colordefs;    const colordef *cr = colordefs + sizeof(colordefs) / sizeof(colordefs[0]);    while (cl < cr) {	const colordef *cm = cl + (cr - cl) / 2;	if (*s == cm->name[0] && s + cm->length == send	    && memcmp(s, cm->name, cm->length) == 0) {	    *r = ((cm->value >> 16) & 0xFF) / 255.;	    *g = ((cm->value >> 8) & 0xFF) / 255.;	    *b = (cm->value & 0xFF) / 255.;	    if (a)		*a = (255 - (cm->value >> 24)) / 255.;	    return true;	}	int cmp;	if (*s < cm->name[0])	    cmp = -1;	else if (*s > cm->name[0])	    cmp = 1;	else {	    int len = (send - s < cm->length ? send - s : cm->length);	    if (!(cmp = memcmp(s, cm->name, len)))		cmp = (cm->length == len ? 1 : -1);	}	if (cmp < 0)	    cr = cm;	else	    cl = cm + 1;    }    return false;}static const char *ccss_skip_braces(const char *s, const char *send,				    bool one_word = false){    int nopen = 0;    for (; s != send; ++s)	if (*s == '/' && s + 1 != send && (s[1] == '/' || s[1] == '*'))	    s = cp_skip_comment_space(s, send) - 1;	else if (*s == '\"' || *s == '\'') {	    char quote = *s;	    for (++s; s != send && *s != quote; ++s)		if (*s == '\\') {		    if (s + 2 < send && s[1] == '\r' && s[2] == '\n')			s += 2;		    else if (s + 1 != send)			++s;		} else if (*s == '\n' || *s == '\r' || *s == '\f')		    break;	    if (s == send)		break;	    if (one_word && !nopen) {		++s;		break;	    }	} else if (*s == '}' && --nopen < 0)	    return s + 1;	else if (*s == '{')	    ++nopen;	else if (one_word && (isspace((unsigned char) *s) || *s == ';'))	    break;    return s;}static String ccss_pop_commavec(String &str){    const char *s = str.begin(), *send = str.end();    int parens = 0, quotes = 0;    const char *sarg = cp_skip_comment_space(s, send);    const char *last_nonsp = sarg - 1;    for (; s != send; ++s) {	if (*s == ',' && !parens && !quotes)	    break;	if (!isspace((unsigned char) *s))	    last_nonsp = s;	if (*s == '\"')	    quotes = !quotes;	else if (*s == '\\' && s + 1 != send)	    ++s;	else if (*s == '(' && !quotes)	    ++parens;	else if (*s == ')' && !quotes && parens)	    --parens;    }    String arg = str.substring(sarg, last_nonsp + 1);    if (s != send)	s = cp_skip_comment_space(s + 1, send);    str = str.substring(s, send);    return arg;}/***** * */inline bool comparison_char(char c){    return c == '=' || c == '!' || c == '>' || c == '<';}inline bool int_match_string(const char *begin, const char *end, int x,			     bool require_comparator = true){    int comparator = *begin++;    if (begin < end && *begin == '=') {	if (comparator == '>')	    comparator = 'G';	else if (comparator == '<')	    comparator = 'L';	++begin;    } else if (comparator == '!')	return false;    else if (!require_comparator && isdigit((unsigned char) comparator)) {	comparator = '=';	--begin;    }    int i;    if (begin + 1 == end)	i = *begin - '0';    else if (!cp_integer(begin, end, 10, &i))	return false;    switch (comparator) {    case '=':	return x == i;    case '!':	return x != i;    case '>':	return x > i;    case '<':	return x < i;    case 'G':	return x >= i;    case 'L':	return x <= i;    default:	return false;    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?