File: color.c

package info (click to toggle)
ips 4.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 664 kB
  • sloc: ansic: 10,438; makefile: 25
file content (317 lines) | stat: -rw-r--r-- 6,122 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
/*
 * Configurable ps-like program.
 * Color support routines.
 *
 * Copyright (c) 2010 David I. Bell
 * Permission is granted to use, distribute, or modify this source,
 * provided that this copyright notice remains intact.
 */

#include <string.h>
#include <memory.h>

#include "ips.h"
#include "expr.h"


/*
 * A pair of color names specifying a foreground and background and
 * an associated set of flags which modify the appearance of the text.
 * If either string is empty then that means use the default
 * foreground or background color.
 */
typedef struct
{
	const char *	foreground;
	const char *	background;
	int		flags;
}
ColorData;


/*
 * The definition of a color to be applied to rows which meet a
 * specified condition.
 */
typedef	struct
{
	int	colorId;		/* color id for row */
	TREE	tree;			/* condition required for coloring */
}
RowColor;


/*
 * The table of color data structures.
 * The table is indexed by the color id, with the first entry being
 * that of the default color id.
 */
static	int		colorCount;
static	ColorData	colorTable[MAX_COLORS];


/*
 * The table of row coloring conditions.
 */
static	int		rowColorCount;
static	RowColor	rowColorTable[MAX_ROW_COLORS];


/*
 * Initialize the color table.
 * This defines the DEFAULT_COLOR_ID entry which has the default
 * foreground and background colors and no color flags.
 */
void
InitializeColors(void)
{
	colorTable[0].foreground = "";
	colorTable[0].background = "";
	colorTable[0].flags = COLOR_FLAG_NONE;

	colorCount = 1;
}


/*
 * Allocate a color id for the specified pair of colors and flags
 * (while returning the same id if the same values are specified again).
 * The string contains a pair of color names separated with a slash.
 * Either name can be empty or the special "default" value to indicate
 * the default foreground or background color.  If there is no slash
 * then only the foreground color is specified.  If a second slash is
 * given then a set of color flag characters are parsed.  Returns the
 * color id on success or BAD_COLOR_ID on an failure.
 */
int
AllocateColor(const char * color)
{
	char *		dupColor;
	char *		slash;
	const char *	foreground;
	const char *	background;
	const char *	flagsString;
	ColorData *	pair;
	int		colorFlags;
	int		colorId;

	/*
	 * Copy the name and split it name into its foreground,
	 * background, and flag parts which are separated by slashes.
	 */
	dupColor = strdup(color);

	if (dupColor == 0)
		return BAD_COLOR_ID;

	foreground = dupColor;
	background = "";
	flagsString = "";

	slash = strchr(dupColor, '/');

	if (slash)
	{
		*slash++ = '\0';
		background = slash;
	}

	if (slash)
		slash = strchr(slash, '/');

	if (slash)
	{
		*slash++ = '\0';
		flagsString = slash;
	}

	/*
	 * Parse the flag characters into bits.
	 */
	colorFlags = COLOR_FLAG_NONE;

	while (*flagsString)
	{
		switch (*flagsString++)
		{
			case 'u':
				colorFlags |= COLOR_FLAG_UNDERLINE;
				break;

			case 'b':
				colorFlags |= COLOR_FLAG_BOLD;
				break;

			default:
				return BAD_COLOR_ID;
		}
	}

	/*
	 * Check for the default name and change it to blank.
	 */
	if (strcmp(foreground, DEFAULT_COLOR_NAME) == 0)
		foreground = "";

	if (strcmp(background, DEFAULT_COLOR_NAME) == 0)
		background = "";

	/*
	 * Search the color table for an existing entry and use that.
	 */
	for (colorId = 0; colorId < colorCount; colorId++)
	{
		pair = &colorTable[colorId];

		if ((strcmp(pair->foreground, foreground) == 0) &&
			(strcmp(pair->background, background) == 0) &&
			(pair->flags == colorFlags))
		{
			return colorId;
		}
	}

	/*
	 * The color pair is new.
	 * Allocate a new entry and return its color id.
	 */
	if (colorCount >= MAX_COLORS)
	{
		free(dupColor);

		return BAD_COLOR_ID;
	}

	pair = &colorTable[colorCount];

	pair->foreground = foreground;
	pair->background = background;
	pair->flags = colorFlags;

	return colorCount++;
}


/*
 * Define all of the colors that have been allocated.
 * This is called within the opening code of the display.
 */
BOOL
DefineColors(void)
{
	int			colorId;
	const ColorData *	colorData;

	for (colorId = 0; colorId < colorCount; colorId++)
	{
		colorData = &colorTable[colorId];

		if (!DpyDefineColor(colorId, colorData->foreground,
			colorData->background, colorData->flags))
		{
			return FALSE;
		}
	}

	return TRUE;
}


/*
 * Clear the row color conditions.
 * This can lose memory but that happens only on startup.
 */
void
ClearRowColorConditions(void)
{
	rowColorCount = 0;
}


/*
 * Allocate and parse a new row coloring entry for the specified condition.
 * The color is a foreground/background/flags value separated by an optional slash.
 * Returns TRUE on success.
 */
BOOL
ParseRowColorCondition(const char * color, const char * condition)
{
	RowColor *	rowColor;

	if (rowColorCount >= MAX_ROW_COLORS)
		return FALSE;

	rowColor = &rowColorTable[rowColorCount];

	rowColor->colorId = AllocateColor(color);

	if (rowColor->colorId == BAD_COLOR_ID)
		return FALSE;

	if (!ParseTree(&rowColor->tree, condition, 0))
		return FALSE;

	rowColorCount++;

	return TRUE;
}


/*
 * Return the use flags for the row color conditions.
 */
USEFLAG
GetRowColorUseFlags(void)
{
	USEFLAG		useFlags = USE_NONE;
	int		index;

	for (index = 0; index < rowColorCount; index++)
	{
		useFlags |= GetNodeUseFlags(rowColorTable[index].tree.root);
	}

	return useFlags;
}


/*
 * Evaluate and return the color id to be used for a process row.
 * The default color is returned if there are no conditions.
 */
int
EvaluateRowColor(const PROC * proc)
{
	int		colorId = DEFAULT_COLOR_ID;
	int		index;
	BOOL		isWanted;
	RowColor *	rowColor;
	VALUE		value;

	for (index = 0; index < rowColorCount; index++)
	{
		isWanted = FALSE;

		rowColor = &rowColorTable[index];

		rowColor->tree.proc = proc;

		value = EvaluateNode(&rowColor->tree, rowColor->tree.root);

		if ((value.type == VALUE_NUMBER) || (value.type == VALUE_BOOLEAN))
		{
			isWanted = (value.intVal != 0);
		}
		else if (value.type == VALUE_STRING)
		{
			isWanted = (*value.strVal != '\0');
		}

		if (isWanted)
			colorId = rowColor->colorId;
	}

	return colorId;
}

/* END CODE */