GRASS GIS 8 Programmer's Manual  8.5.0dev(2024)-83537f72e2
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 <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include <grass/gis.h>
16 #include <grass/glocale.h>
17 
18 struct colorinfo {
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, sizeof(struct colorinfo),
209  cmp_clrname);
210 
211  if (cfound) {
212  if (cfound->desc) {
213  fprintf(out, "%s: %s [%s]\n", cfound->name, cfound->desc,
214  cfound->type);
215  }
216  else {
217  fprintf(out, "%s: [%s]\n", cfound->name, cfound->type);
218  }
219  }
220  }
221 
222  if (cfound == NULL) {
223  for (i = 0; i < nrules; i++) {
224  if (colorinfo[i].desc) {
225  fprintf(out, "%s: %s [%s]\n", colorinfo[i].name,
226  colorinfo[i].desc, colorinfo[i].type);
227  }
228  else {
229  fprintf(out, "%s: [%s]\n", colorinfo[i].name,
230  colorinfo[i].type);
231  }
232  }
233  }
234 
235  free_colorinfo(colorinfo, nrules);
236 }
237 
238 /*!
239  \brief Check if color rule is defined
240 
241  \param name color rule name
242 
243  \return 1 found
244  \return 0 not found
245  */
246 int G_find_color_rule(const char *name)
247 {
248  int result, nrules;
249  struct colorinfo *colorinfo, csearch;
250 
251  colorinfo = get_colorinfo(&nrules);
252 
253  csearch.name = (char *)name;
254  result = (bsearch(&csearch, colorinfo, nrules, sizeof(struct colorinfo),
255  cmp_clrname) != NULL);
256 
257  free_colorinfo(colorinfo, nrules);
258 
259  return result;
260 }
261 
262 struct colorinfo *get_colorinfo(int *nrules)
263 {
264  int i;
265  char path[GPATH_MAX];
266  FILE *fp;
267  struct colorinfo *colorinfo;
268  char **cnames;
269 
270  /* load color rules */
271  snprintf(path, GPATH_MAX, "%s/etc/colors", G_gisbase());
272 
273  *nrules = 0;
274  cnames = G_ls2(path, nrules);
275  (*nrules) += 3;
276  colorinfo = G_malloc(*nrules * sizeof(struct colorinfo));
277  for (i = 0; i < *nrules - 3; i++) {
278  char buf[1024];
279  double rmin, rmax;
280  int first;
281  int cisperc;
282 
283  colorinfo[i].name = G_store(cnames[i]);
284  colorinfo[i].desc = NULL;
285 
286  /* open color rule file */
287  snprintf(path, GPATH_MAX, "%s/etc/colors/%s", G_gisbase(),
288  colorinfo[i].name);
289  fp = fopen(path, "r");
290  if (!fp)
291  G_fatal_error(_("Unable to open color rule"));
292 
293  /* scan all lines */
294  first = 1;
295  rmin = rmax = 0;
296  cisperc = 0;
297  while (G_getl2(buf, sizeof(buf), fp)) {
298  char value[80], color[80];
299  double x;
300  char c;
301 
302  G_strip(buf);
303 
304  if (*buf == '\0')
305  continue;
306  if (*buf == '#')
307  continue;
308 
309  if (sscanf(buf, "%s %[^\n]", value, color) != 2)
310  continue;
311 
312  if (G_strcasecmp(value, "default") == 0) {
313  continue;
314  }
315 
316  if (G_strcasecmp(value, "nv") == 0) {
317  continue;
318  }
319 
320  if (sscanf(value, "%lf%c", &x, &c) == 2 && c == '%') {
321  cisperc = 1;
322  break;
323  }
324  if (sscanf(value, "%lf", &x) == 1) {
325  if (first) {
326  first = 0;
327  rmin = rmax = x;
328  }
329  else {
330  if (rmin > x)
331  rmin = x;
332  if (rmax < x)
333  rmax = x;
334  }
335  }
336  }
337  fclose(fp);
338 
339  if (cisperc)
340  colorinfo[i].type = G_store(_("range: map values"));
341  else {
342  snprintf(buf, sizeof(buf) - 1, _("range: %g to %g"), rmin, rmax);
343  colorinfo[i].type = G_store(buf);
344  }
345  }
346  G_free(cnames);
347 
348  /* colors without rules but description */
349  colorinfo[*nrules - 3].name = G_store("random");
350  colorinfo[*nrules - 3].desc = NULL;
351  colorinfo[*nrules - 3].type = G_store(_("range: map values"));
352 
353  colorinfo[*nrules - 2].name = G_store("grey.eq");
354  colorinfo[*nrules - 2].desc = NULL;
355  colorinfo[*nrules - 2].type = G_store(_("range: map values"));
356 
357  colorinfo[*nrules - 1].name = G_store("grey.log");
358  colorinfo[*nrules - 1].desc = NULL;
359  colorinfo[*nrules - 1].type = G_store(_("range: map values"));
360 
361  qsort(colorinfo, *nrules, sizeof(struct colorinfo), cmp_clrname);
362 
363  /* load color descriptions */
364  snprintf(path, GPATH_MAX, "%s/etc/colors.desc", G_gisbase());
365  fp = fopen(path, "r");
366  if (!fp)
367  G_fatal_error(_("Unable to open color descriptions"));
368 
369  for (;;) {
370  char buf[1024];
371  char tok_buf[1024];
372  char *cname, *cdesc;
373  int ntokens;
374  char **tokens;
375  struct colorinfo csearch, *cfound;
376 
377  if (!G_getl2(buf, sizeof(buf), fp))
378  break;
379  strcpy(tok_buf, buf);
380  tokens = G_tokenize(tok_buf, ":");
381  ntokens = G_number_of_tokens(tokens);
382  if (ntokens != 2)
383  continue;
384 
385  cname = G_chop(tokens[0]);
386  cdesc = G_chop(tokens[1]);
387 
388  csearch.name = cname;
389  cfound = bsearch(&csearch, colorinfo, *nrules, sizeof(struct colorinfo),
390  cmp_clrname);
391 
392  if (cfound) {
393  cfound->desc = G_store(cdesc);
394  }
395  G_free_tokens(tokens);
396  }
397  fclose(fp);
398 
399  return colorinfo;
400 }
401 
402 void free_colorinfo(struct colorinfo *colorinfo, int nrules)
403 {
404  int i;
405 
406  for (i = 0; i < nrules; i++) {
407  if (colorinfo[i].name)
408  G_free(colorinfo[i].name);
409  if (colorinfo[i].desc)
410  G_free(colorinfo[i].desc);
411  if (colorinfo[i].type)
412  G_free(colorinfo[i].type);
413  }
414  if (nrules > 0)
415  G_free(colorinfo);
416 }
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:60
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
#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