GRASS GIS 8 Programmer's Manual  8.2.2dev(2023)-3d2c704037
gis/color_rules.c
Go to the documentation of this file.
1 /*!
2  \file lib/gis/color_rules.c
3 
4  \brief GIS Library - Color tables management subroutines
5 
6  Taken from r.colors module.
7 
8  (C) 2001-2011 by the GRASS Development Team
9 */
10 
11 #include <stdlib.h>
12 #include <string.h>
13 
14 #include <grass/gis.h>
15 #include <grass/glocale.h>
16 
17 struct colorinfo
18 {
19  char *name;
20  char *desc;
21  char *type;
22 };
23 
24 static struct colorinfo *get_colorinfo(int *);
25 static void free_colorinfo(struct colorinfo *, int);
26 
27 static int cmp_clrname(const void *a, const void *b)
28 {
29  struct colorinfo *ca = (struct colorinfo *) a;
30  struct colorinfo *cb = (struct colorinfo *) b;
31 
32  return (strcmp(ca->name, cb->name));
33 }
34 
35 /*!
36  \brief Get list of color rules for Option->options
37 
38  \return allocated string buffer with options
39 */
41 {
42  char *list;
43  const char *name;
44  int size, len, nrules;
45  int i, n;
46  struct colorinfo *colorinfo;
47 
48  list = NULL;
49  size = len = 0;
50 
51  colorinfo = get_colorinfo(&nrules);
52 
53  for (i = 0; i < nrules; i++) {
54  name = colorinfo[i].name;
55  n = strlen(name);
56 
57  if (size < len + n + 2) {
58  size = len + n + 200;
59  list = G_realloc(list, size);
60  }
61 
62  if (len > 0)
63  list[len++] = ',';
64 
65  memcpy(&list[len], name, n + 1);
66  len += n;
67  }
68 
69  free_colorinfo(colorinfo, nrules);
70 
71  return list;
72 }
73 
74 /*!
75  \brief Get color rules description for Option->descriptions
76 
77  \return allocated buffer with descriptions
78 */
80 {
81  int result_len, result_max;
82  char *result;
83  const char *name, *desc;
84  int i, len, nrules;
85  struct colorinfo *colorinfo;
86 
87  result_len = 0;
88  result_max = 2000;
89  result = G_malloc(result_max);
90 
91  colorinfo = get_colorinfo(&nrules);
92 
93  for (i = 0; i < nrules; i++) {
94  name = colorinfo[i].name;
95  desc = colorinfo[i].desc;
96 
97  if (!desc)
98  desc = _("no description");
99 
100  /* desc = _(desc); */
101 
102  len = strlen(name) + strlen(desc) + 2;
103  if (result_len + len >= result_max) {
104  result_max = result_len + len + 1000;
105  result = G_realloc(result, result_max);
106  }
107 
108  sprintf(result + result_len, "%s;%s;", name, desc);
109  result_len += len;
110  }
111 
112  free_colorinfo(colorinfo, nrules);
113 
114  return result;
115 }
116 
117 /*!
118  \brief Get color rules description for Option->descriptions
119 
120  The type of color rule including range is appended to the description
121 
122  \return allocated buffer with name, description, and type
123 */
125 {
126  int i, len, nrules;
127  struct colorinfo *colorinfo;
128  const char *name, *desc, *type;
129  int result_len, result_max;
130  char *result;
131 
132  colorinfo = get_colorinfo(&nrules);
133 
134  result_len = 0;
135  result_max = 2000;
136  result = G_malloc(result_max);
137 
138  for (i = 0; i < nrules; i++) {
139  name = colorinfo[i].name;
140  desc = colorinfo[i].desc;
141  type = colorinfo[i].type;
142 
143  if (desc) {
144  len = strlen(name) + strlen(desc) + strlen(type) + 5;
145  if (result_len + len >= result_max) {
146  result_max = result_len + len + 1000;
147  result = G_realloc(result, result_max);
148  }
149 
150  sprintf(result + result_len, "%s;%s [%s];", name, desc, type);
151  result_len += len;
152  }
153  else {
154  len = strlen(name) + strlen(type) + 5;
155  if (result_len + len >= result_max) {
156  result_max = result_len + len + 1000;
157  result = G_realloc(result, result_max);
158  }
159 
160  sprintf(result + result_len, "%s; [%s];", name, type);
161  result_len += len;
162  }
163  }
164 
165  free_colorinfo(colorinfo, nrules);
166 
167  return result;
168 }
169 
170 /*!
171  \brief Print color rules
172 
173  \param out file where to print
174 */
175 void G_list_color_rules(FILE *out)
176 {
177  int i, nrules;
178  struct colorinfo *colorinfo;
179 
180  colorinfo = get_colorinfo(&nrules);
181 
182  for (i = 0; i < nrules; i++)
183  fprintf(out, "%s\n", colorinfo[i].name);
184 
185  free_colorinfo(colorinfo, nrules);
186 }
187 
188 /*!
189  \brief Print color rules with description and type
190 
191  The type of color rule including range is appended to the description.
192  If a color rule name is given, color info is printed only for this
193  rule.
194 
195  \param name optional color rule name, or NULL
196  \param out file where to print
197 */
199 {
200  int i, nrules;
201  struct colorinfo *colorinfo, csearch, *cfound;
202 
203  colorinfo = get_colorinfo(&nrules);
204 
205  cfound = NULL;
206  if (name) {
207  csearch.name = name;
208  cfound = bsearch(&csearch, colorinfo, nrules,
209  sizeof(struct colorinfo), cmp_clrname);
210 
211  if (cfound) {
212  if (cfound->desc) {
213  fprintf(out, "%s: %s [%s]\n", cfound->name,
214  cfound->desc, cfound->type);
215  }
216  else {
217  fprintf(out, "%s: [%s]\n", cfound->name,
218  cfound->type);
219  }
220  }
221  }
222 
223  if (cfound == NULL) {
224  for (i = 0; i < nrules; i++) {
225  if (colorinfo[i].desc) {
226  fprintf(out, "%s: %s [%s]\n", colorinfo[i].name,
227  colorinfo[i].desc, colorinfo[i].type);
228  }
229  else {
230  fprintf(out, "%s: [%s]\n", colorinfo[i].name,
231  colorinfo[i].type);
232  }
233  }
234  }
235 
236  free_colorinfo(colorinfo, nrules);
237 }
238 
239 /*!
240  \brief Check if color rule is defined
241 
242  \param name color rule name
243 
244  \return 1 found
245  \return 0 not found
246 */
247 int G_find_color_rule(const char *name)
248 {
249  int result, nrules;
250  struct colorinfo *colorinfo, csearch;
251 
252  colorinfo = get_colorinfo(&nrules);
253 
254  csearch.name = (char *)name;
255  result = (bsearch(&csearch, colorinfo, nrules,
256  sizeof(struct colorinfo), cmp_clrname) != NULL);
257 
258  free_colorinfo(colorinfo, nrules);
259 
260  return result;
261 }
262 
263 struct colorinfo *get_colorinfo(int *nrules)
264 {
265  int i;
266  char path[GPATH_MAX];
267  FILE *fp;
268  struct colorinfo *colorinfo;
269  char **cnames;
270 
271  /* load color rules */
272  G_snprintf(path, GPATH_MAX, "%s/etc/colors", G_gisbase());
273 
274  *nrules = 0;
275  cnames = G_ls2(path, nrules);
276  (*nrules) += 3;
277  colorinfo = G_malloc(*nrules * sizeof(struct colorinfo));
278  for (i = 0; i < *nrules - 3; i++) {
279  char buf[1024];
280  double rmin, rmax;
281  int first;
282  int cisperc;
283 
284  colorinfo[i].name = G_store(cnames[i]);
285  colorinfo[i].desc = NULL;
286 
287  /* open color rule file */
288  G_snprintf(path, GPATH_MAX, "%s/etc/colors/%s", G_gisbase(),
289  colorinfo[i].name);
290  fp = fopen(path, "r");
291  if (!fp)
292  G_fatal_error(_("Unable to open color rule"));
293 
294  /* scan all lines */
295  first = 1;
296  rmin = rmax = 0;
297  cisperc = 0;
298  while (G_getl2(buf, sizeof(buf), fp)) {
299  char value[80], color[80];
300  double x;
301  char c;
302 
303  G_strip(buf);
304 
305  if (*buf == '\0')
306  continue;
307  if (*buf == '#')
308  continue;
309 
310  if (sscanf(buf, "%s %[^\n]", value, color) != 2)
311  continue;
312 
313  if (G_strcasecmp(value, "default") == 0) {
314  continue;
315  }
316 
317  if (G_strcasecmp(value, "nv") == 0) {
318  continue;
319  }
320 
321  if (sscanf(value, "%lf%c", &x, &c) == 2 && c == '%') {
322  cisperc = 1;
323  break;
324  }
325  if (sscanf(value, "%lf", &x) == 1) {
326  if (first) {
327  first = 0;
328  rmin = rmax = x;
329  }
330  else {
331  if (rmin > x)
332  rmin = x;
333  if (rmax < x)
334  rmax = x;
335  }
336  }
337  }
338  fclose(fp);
339 
340  if (cisperc)
341  colorinfo[i].type = G_store(_("range: map values"));
342  else {
343  G_snprintf(buf, sizeof(buf) - 1, _("range: %g to %g"), rmin, rmax);
344  colorinfo[i].type = G_store(buf);
345  }
346  }
347  G_free(cnames);
348 
349  /* colors without rules but description */
350  colorinfo[*nrules - 3].name = G_store("random");
351  colorinfo[*nrules - 3].desc = NULL;
352  colorinfo[*nrules - 3].type = G_store(_("range: map values"));
353 
354  colorinfo[*nrules - 2].name = G_store("grey.eq");
355  colorinfo[*nrules - 2].desc = NULL;
356  colorinfo[*nrules - 2].type = G_store(_("range: map values"));
357 
358  colorinfo[*nrules - 1].name = G_store("grey.log");
359  colorinfo[*nrules - 1].desc = NULL;
360  colorinfo[*nrules - 1].type = G_store(_("range: map values"));
361 
362  qsort(colorinfo, *nrules, sizeof(struct colorinfo), cmp_clrname);
363 
364  /* load color descriptions */
365  G_snprintf(path, GPATH_MAX, "%s/etc/colors.desc", G_gisbase());
366  fp = fopen(path, "r");
367  if (!fp)
368  G_fatal_error(_("Unable to open color descriptions"));
369 
370  for (;;) {
371  char buf[1024];
372  char tok_buf[1024];
373  char *cname, *cdesc;
374  int ntokens;
375  char **tokens;
376  struct colorinfo csearch, *cfound;
377 
378  if (!G_getl2(buf, sizeof(buf), fp))
379  break;
380  strcpy(tok_buf, buf);
381  tokens = G_tokenize(tok_buf, ":");
382  ntokens = G_number_of_tokens(tokens);
383  if (ntokens != 2)
384  continue;
385 
386  cname = G_chop(tokens[0]);
387  cdesc = G_chop(tokens[1]);
388 
389  csearch.name = cname;
390  cfound = bsearch(&csearch, colorinfo, *nrules,
391  sizeof(struct colorinfo), cmp_clrname);
392 
393  if (cfound) {
394  cfound->desc = G_store(cdesc);
395  }
396  G_free_tokens(tokens);
397  }
398  fclose(fp);
399 
400  return colorinfo;
401 }
402 
403 void free_colorinfo(struct colorinfo *colorinfo, int nrules)
404 {
405  int i;
406 
407  for (i = 0; i < nrules; i++) {
408  if (colorinfo[i].name)
409  G_free(colorinfo[i].name);
410  if (colorinfo[i].desc)
411  G_free(colorinfo[i].desc);
412  if (colorinfo[i].type)
413  G_free(colorinfo[i].type);
414  }
415  if (nrules > 0)
416  G_free(colorinfo);
417 }
int G_getl2(char *, int, FILE *)
Gets a line of text from a file of any pedigree.
Definition: getl.c:64
#define G_malloc(n)
Definition: defs/gis.h:112
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
int G_find_color_rule(const char *name)
Check if color rule is defined.
struct cairo_state ca
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:149
void G_list_color_rules(FILE *out)
Print color rules.
void G_strip(char *)
Removes all leading and trailing white space from string.
Definition: strings.c:300
char ** G_ls2(const char *, int *)
Stores a sorted directory listing in an array.
Definition: ls.c:95
char ** G_tokenize(const char *, const char *)
Tokenize string.
Definition: gis/token.c:48
#define NULL
Definition: ccmath.h:32
#define x
char * G_color_rules_description_type(void)
Get color rules description for Option->descriptions.
int int G_strcasecmp(const char *, const char *)
String compare ignoring case (upper or lower)
Definition: strings.c:47
double b
Definition: r_raster.c:39
struct list * list
Definition: read_list.c:24
void G_list_color_rules_description_type(FILE *out, char *name)
Print color rules with description and type.
int G_number_of_tokens(char **)
Return number of tokens.
Definition: gis/token.c:185
#define GPATH_MAX
Definition: gis.h:180
char * G_chop(char *)
Chop leading and trailing white spaces.
Definition: strings.c:328
int G_snprintf(char *, size_t, const char *,...) __attribute__((format(printf
const char * G_gisbase(void)
Get full path name of the top level module directory.
Definition: gisbase.c:41
void G_free_tokens(char **)
Free memory allocated to tokens.
Definition: gis/token.c:204
Definition: path.h:16
#define G_realloc(p, n)
Definition: defs/gis.h:114
#define _(str)
Definition: glocale.h:10
char * G_color_rules_descriptions(void)
Get color rules description for Option->descriptions.
char * G_color_rules_options(void)
Get list of color rules for Option->options.
char * G_store(const char *)
Copy string to allocated memory.
Definition: strings.c:87
const char * name
Definition: named_colr.c:7