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