NetSurf
nsoption.c
Go to the documentation of this file.
1/*
2 * Copyright 2012 Vincent Sanders <vince@netsurf-browser.org>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/**
20 * \file
21 * Option reading and saving (implementation).
22 *
23 * Options are stored in the format key:value, one per line.
24 *
25 * For bool options, value is "0" or "1".
26 */
27
28#include <stdio.h>
29#include <stdint.h>
30#include <stdbool.h>
31#include <stdlib.h>
32#include <string.h>
33#include <strings.h>
34
35#include "netsurf/inttypes.h"
36#include "netsurf/plot_style.h"
37#include "utils/errors.h"
38#include "utils/log.h"
39#include "utils/utils.h"
40#include "utils/nsoption.h"
41
42/** Length of buffer used to read lines from input file */
43#define NSOPTION_MAX_LINE_LEN 1024
44
45struct nsoption_s *nsoptions = NULL;
47
48#define NSOPTION_BOOL(NAME, DEFAULT) \
49 { #NAME, sizeof(#NAME) - 1, OPTION_BOOL, { .b = DEFAULT } },
50
51#define NSOPTION_STRING(NAME, DEFAULT) \
52 { #NAME, sizeof(#NAME) - 1, OPTION_STRING, { .cs = DEFAULT } },
53
54#define NSOPTION_INTEGER(NAME, DEFAULT) \
55 { #NAME, sizeof(#NAME) - 1, OPTION_INTEGER, { .i = DEFAULT } },
56
57#define NSOPTION_UINT(NAME, DEFAULT) \
58 { #NAME, sizeof(#NAME) - 1, OPTION_UINT, { .u = DEFAULT } },
59
60#define NSOPTION_COLOUR(NAME, DEFAULT) \
61 { #NAME, sizeof(#NAME) - 1, OPTION_COLOUR, { .c = DEFAULT } },
62
63/** The table of compiled in default options */
64static struct nsoption_s defaults[] = {
65#include "desktop/options.h"
66
67#if defined(riscos)
68#include "riscos/options.h"
69#elif defined(nsgtk)
70#include "gtk/options.h"
71#elif defined(nsbeos)
72#include "beos/options.h"
73#elif defined(nsamiga)
74#include "amiga/options.h"
75#elif defined(nsframebuffer)
76#include "framebuffer/options.h"
77#elif defined(nsatari)
78#include "atari/options.h"
79#elif defined(nsmonkey)
80#include "monkey/options.h"
81#elif defined(nswin32)
82#include "windows/options.h"
83#endif
84 { NULL, 0, OPTION_INTEGER, { 0 } }
85};
86
87#undef NSOPTION_BOOL
88#undef NSOPTION_STRING
89#undef NSOPTION_INTEGER
90#undef NSOPTION_UINT
91#undef NSOPTION_COLOUR
92
93/**
94 * Set an option value based on a string
95 */
96static bool
97strtooption(const char *value, struct nsoption_s *option)
98{
99 bool ret = true;
100 colour rgbcolour; /* RRGGBB */
101
102 switch (option->type) {
103 case OPTION_BOOL:
104 option->value.b = (value[0] == '1');
105 break;
106
107 case OPTION_INTEGER:
108 option->value.i = atoi(value);
109 break;
110
111 case OPTION_UINT:
112 option->value.u = strtoul(value, NULL, 0);
113 break;
114
115 case OPTION_COLOUR:
116 if (sscanf(value, "%"SCNx32"", &rgbcolour) == 1) {
117 option->value.c = (((0x000000FF & rgbcolour) << 16) |
118 ((0x0000FF00 & rgbcolour) << 0) |
119 ((0x00FF0000 & rgbcolour) >> 16));
120 }
121 break;
122
123 case OPTION_STRING:
124 if (option->value.s != NULL) {
125 free(option->value.s);
126 }
127
128 if (*value == 0) {
129 /* do not allow empty strings in text options */
130 option->value.s = NULL;
131 } else {
132 option->value.s = strdup(value);
133 }
134 break;
135
136 default:
137 ret = false;
138 break;
139 }
140
141 return ret;
142}
143
144/* validate options to sane values */
145static void nsoption_validate(struct nsoption_s *opts, struct nsoption_s *defs)
146{
147 int cloop;
148 bool black = true;
149
150 if (opts[NSOPTION_treeview_font_size].value.i < 50) {
151 opts[NSOPTION_treeview_font_size].value.i = 50;
152 }
153
154 if (opts[NSOPTION_treeview_font_size].value.i > 1000) {
155 opts[NSOPTION_treeview_font_size].value.i = 1000;
156 }
157
158 if (opts[NSOPTION_font_size].value.i < 50) {
159 opts[NSOPTION_font_size].value.i = 50;
160 }
161
162 if (opts[NSOPTION_font_size].value.i > 1000) {
163 opts[NSOPTION_font_size].value.i = 1000;
164 }
165
166 if (opts[NSOPTION_font_min_size].value.i < 10) {
167 opts[NSOPTION_font_min_size].value.i = 10;
168 }
169
170 if (opts[NSOPTION_font_min_size].value.i > 500) {
171 opts[NSOPTION_font_min_size].value.i = 500;
172 }
173
174 if (opts[NSOPTION_memory_cache_size].value.i < 0) {
175 opts[NSOPTION_memory_cache_size].value.i = 0;
176 }
177
178 /* to aid migration from old, broken, configuration files this
179 * checks to see if all the system colours are set to black
180 * and returns them to defaults instead
181 */
182
183 for (cloop = NSOPTION_SYS_COLOUR_START;
185 cloop++) {
186 if (opts[cloop].value.c != 0) {
187 black = false;
188 break;
189 }
190 }
191 if (black == true && defs != NULL) {
192 for (cloop = NSOPTION_SYS_COLOUR_START;
194 cloop++) {
195 opts[cloop].value.c = defs[cloop].value.c;
196 }
197 }
198
199 /* To aid migration and ensure that timeouts don't go crazy,
200 * ensure that (a) we allow at least 1 attempt and
201 * (b) the total time that we spend should not exceed 60s
202 */
203 if (opts[NSOPTION_max_retried_fetches].value.u == 0)
204 opts[NSOPTION_max_retried_fetches].value.u = 1;
205 if (opts[NSOPTION_curl_fetch_timeout].value.u < 5)
206 opts[NSOPTION_curl_fetch_timeout].value.u = 5;
207 if (opts[NSOPTION_curl_fetch_timeout].value.u > 60)
208 opts[NSOPTION_curl_fetch_timeout].value.u = 60;
209 while (((opts[NSOPTION_curl_fetch_timeout].value.u *
210 opts[NSOPTION_max_retried_fetches].value.u) > 60) &&
211 (opts[NSOPTION_max_retried_fetches].value.u > 1))
212 opts[NSOPTION_max_retried_fetches].value.u--;
213
214 /* We ignore the result because we can't fail to validate. Yay */
216}
217
218/**
219 * Determines if an option is different between two option tables.
220 *
221 * @param opts The first table to compare.
222 * @param defs The second table to compare.
223 * @param entry The option to compare.
224 * @return true if the option differs false if not.
225 */
226static bool
227nsoption_is_set(const struct nsoption_s *opts,
228 const struct nsoption_s *defs,
229 const enum nsoption_e entry)
230{
231 bool ret = false;
232
233 switch (opts[entry].type) {
234 case OPTION_BOOL:
235 if (opts[entry].value.b != defs[entry].value.b) {
236 ret = true;
237 }
238 break;
239
240 case OPTION_INTEGER:
241 if (opts[entry].value.i != defs[entry].value.i) {
242 ret = true;
243 }
244 break;
245
246 case OPTION_UINT:
247 if (opts[entry].value.u != defs[entry].value.u) {
248 ret = true;
249 }
250 break;
251
252 case OPTION_COLOUR:
253 if (opts[entry].value.c != defs[entry].value.c) {
254 ret = true;
255 }
256 break;
257
258 case OPTION_STRING:
259 /* set if:
260 * - defs is null.
261 * - default is null but value is not.
262 * - default and value pointers are different
263 * (acts as a null check because of previous check)
264 * and the strings content differ.
265 */
266 if (((defs[entry].value.s == NULL) &&
267 (opts[entry].value.s != NULL)) ||
268 ((defs[entry].value.s != NULL) &&
269 (opts[entry].value.s == NULL)) ||
270 ((defs[entry].value.s != opts[entry].value.s) &&
271 (strcmp(opts[entry].value.s, defs[entry].value.s) != 0))) {
272 ret = true;
273 }
274 break;
275
276 }
277 return ret;
278}
279
280/**
281 * Output choices to file stream
282 *
283 * @param fp The file stream to write to.
284 * @param opts The options table to write.
285 * @param defs The default value table to compare with.
286 * @param all Output all entries not just ones changed from defaults
287 */
288static nserror
290 struct nsoption_s *opts,
291 struct nsoption_s *defs,
292 bool all)
293{
294 unsigned int entry; /* index to option being output */
295 colour rgbcolour; /* RRGGBB */
296
297 for (entry = 0; entry < NSOPTION_LISTEND; entry++) {
298 if ((all == false) &&
299 (nsoption_is_set(opts, defs, entry) == false)) {
300 continue;
301 }
302
303 switch (opts[entry].type) {
304 case OPTION_BOOL:
305 fprintf(fp, "%s:%c\n",
306 opts[entry].key,
307 opts[entry].value.b ? '1' : '0');
308 break;
309
310 case OPTION_INTEGER:
311 fprintf(fp, "%s:%i\n",
312 opts[entry].key,
313 opts[entry].value.i);
314
315 break;
316
317 case OPTION_UINT:
318 fprintf(fp, "%s:%u\n",
319 opts[entry].key,
320 opts[entry].value.u);
321 break;
322
323 case OPTION_COLOUR:
324 rgbcolour = (((0x000000FF & opts[entry].value.c) << 16) |
325 ((0x0000FF00 & opts[entry].value.c) << 0) |
326 ((0x00FF0000 & opts[entry].value.c) >> 16));
327 fprintf(fp, "%s:%06"PRIx32"\n",
328 opts[entry].key,
329 rgbcolour);
330
331 break;
332
333 case OPTION_STRING:
334 fprintf(fp, "%s:%s\n",
335 opts[entry].key,
336 ((opts[entry].value.s == NULL) ||
337 (*opts[entry].value.s == 0)) ? "" : opts[entry].value.s);
338
339 break;
340 }
341 }
342
343 return NSERROR_OK;
344}
345
346/**
347 * Output an option value into a string, in HTML format.
348 *
349 * @param option The option to output the value of.
350 * @param size The size of the string buffer.
351 * @param pos The current position in string
352 * @param string The string in which to output the value.
353 * @return The number of bytes written to string or -1 on error
354 */
355static size_t
357 size_t size,
358 size_t pos,
359 char *string)
360{
361 size_t slen = 0; /* length added to string */
362 colour rgbcolour; /* RRGGBB */
363
364 switch (option->type) {
365 case OPTION_BOOL:
366 slen = snprintf(string + pos,
367 size - pos,
368 "%s",
369 option->value.b ? "true" : "false");
370 break;
371
372 case OPTION_INTEGER:
373 slen = snprintf(string + pos,
374 size - pos,
375 "%i",
376 option->value.i);
377 break;
378
379 case OPTION_UINT:
380 slen = snprintf(string + pos,
381 size - pos,
382 "%u",
383 option->value.u);
384 break;
385
386 case OPTION_COLOUR:
387 rgbcolour = colour_rb_swap(option->value.c);
388 slen = snprintf(string + pos,
389 size - pos,
390 "<span style=\"font-family:Monospace;\">"
391 "#%06"PRIX32
392 "</span> "
393 "<span style=\"background-color: #%06"PRIx32"; "
394 "border: 1px solid #%06"PRIx32"; "
395 "display: inline-block; "
396 "width: 1em; height: 1em;\">"
397 "</span>",
398 rgbcolour,
399 rgbcolour,
400 colour_to_bw_furthest(rgbcolour));
401 break;
402
403 case OPTION_STRING:
404 if (option->value.s != NULL) {
405 slen = snprintf(string + pos, size - pos, "%s",
406 option->value.s);
407 } else {
408 slen = snprintf(string + pos, size - pos,
409 "<span class=\"null-content\">NULL"
410 "</span>");
411 }
412 break;
413 }
414
415 return slen;
416}
417
418
419/**
420 * Output an option value into a string, in plain text format.
421 *
422 * @param option The option to output the value of.
423 * @param size The size of the string buffer.
424 * @param pos The current position in string
425 * @param string The string in which to output the value.
426 * @return The number of bytes written to string or -1 on error
427 */
428static size_t
430 size_t size,
431 size_t pos,
432 char *string)
433{
434 size_t slen = 0; /* length added to string */
435 colour rgbcolour; /* RRGGBB */
436
437 switch (option->type) {
438 case OPTION_BOOL:
439 slen = snprintf(string + pos,
440 size - pos,
441 "%c",
442 option->value.b ? '1' : '0');
443 break;
444
445 case OPTION_INTEGER:
446 slen = snprintf(string + pos,
447 size - pos,
448 "%i",
449 option->value.i);
450 break;
451
452 case OPTION_UINT:
453 slen = snprintf(string + pos,
454 size - pos,
455 "%u",
456 option->value.u);
457 break;
458
459 case OPTION_COLOUR:
460 rgbcolour = (((0x000000FF & option->value.c) << 16) |
461 ((0x0000FF00 & option->value.c) << 0) |
462 ((0x00FF0000 & option->value.c) >> 16));
463 slen = snprintf(string + pos, size - pos, "%06"PRIx32, rgbcolour);
464 break;
465
466 case OPTION_STRING:
467 if (option->value.s != NULL) {
468 slen = snprintf(string + pos,
469 size - pos,
470 "%s",
471 option->value.s);
472 }
473 break;
474 }
475
476 return slen;
477}
478
479/**
480 * Duplicates an option table.
481 *
482 * Allocates a new option table and copies an existing one into it.
483 *
484 * \param[in] src The source table to copy
485 * \param[out] pdst The output table
486 * \return NSERROR_OK on success or appropriate error code.
487 */
488static nserror
489nsoption_dup(struct nsoption_s *src, struct nsoption_s **pdst)
490{
491 struct nsoption_s *dst;
492 dst = malloc(sizeof(defaults));
493 if (dst == NULL) {
494 return NSERROR_NOMEM;
495 }
496 *pdst = dst;
497
498 /* copy the source table into the destination table */
499 memcpy(dst, src, sizeof(defaults));
500
501 while (src->key != NULL) {
502 if ((src->type == OPTION_STRING) &&
503 (src->value.s != NULL)) {
504 dst->value.s = strdup(src->value.s);
505 }
506 src++;
507 dst++;
508 }
509
510 return NSERROR_OK;
511}
512
513/**
514 * frees an option table.
515 *
516 * Iterates through an option table a freeing resources as required
517 * finally freeing the option table itself.
518 *
519 * @param opts The option table to free.
520 */
521static nserror
523{
524 struct nsoption_s *cur; /* option being freed */
525
526 if (opts == NULL) {
528 }
529
530 cur = opts;
531
532 while (cur->key != NULL) {
533 if ((cur->type == OPTION_STRING) && (cur->value.s != NULL)) {
534 free(cur->value.s);
535 }
536 cur++;
537 }
538 free(opts);
539
540 return NSERROR_OK;
541}
542
543
544/**
545 * extract key/value from a line of input
546 *
547 * \retun NSERROR_OK and key_out and value_out updated
548 * NSERROR_NOT_FOUND if not a key/value input line
549 * NSERROR_INVALID if the line is and invalid format (missing colon)
550 */
551static nserror
552get_key_value(char *line, int linelen, char **key_out, char **value_out)
553{
554 char *key;
555 char *value;
556
557 /* skip leading whitespace for start of key */
558 for (key = line; *key != 0; key++) {
559 if ((*key != ' ') && (*key != '\t') && (*key != '\n')) {
560 break;
561 }
562 }
563
564 /* empty line or only whitespace */
565 if (*key == 0) {
566 return NSERROR_NOT_FOUND;
567 }
568
569 /* comment */
570 if (*key == '#') {
571 return NSERROR_NOT_FOUND;
572 }
573
574 /* get start of value */
575 for (value = key; *value != 0; value++) {
576 if (*value == ':') {
577 *value = 0;
578 value++;
579 break;
580 }
581 }
582
583 /* missing colon separator */
584 if (*value == 0) {
585 return NSERROR_INVALID;
586 }
587
588 /* remove delimiter from value */
589 if (line[linelen - 1] == '\n') {
590 linelen--;
591 line[linelen] = 0;
592 }
593
594 *key_out = key;
595 *value_out = value;
596 return NSERROR_OK;
597}
598
599
600/**
601 * Process a line from a user option file
602 */
603static nserror optionline(struct nsoption_s *opts, char *line, int linelen)
604{
605 nserror res;
606 char *key;
607 char *value;
608 int idx;
609
610 res = get_key_value(line, linelen, &key, &value);
611 if (res != NSERROR_OK) {
612 /* skip line as no valid key value pair found */
613 return res;
614 }
615
616 for (idx = 0; opts[idx].key != NULL; idx++) {
617 if (strcasecmp(key, opts[idx].key) == 0) {
618 strtooption(value, &opts[idx]);
619 break;
620 }
621 }
622
623 return res;
624}
625
626
627/* exported interface documented in utils/nsoption.h */
630 struct nsoption_s **popts,
631 struct nsoption_s **pdefs)
632{
633 nserror ret;
634 struct nsoption_s *defs;
635 struct nsoption_s *opts;
636
637 ret = nsoption_dup(&defaults[0], &defs);
638 if (ret != NSERROR_OK) {
639 return ret;
640 }
641
642 /* update the default table */
643 if (set_defaults != NULL) {
644 /** @todo it would be better if the frontends actually
645 * set values in the passed in table instead of
646 * assuming the global one.
647 */
648 opts = nsoptions;
649 nsoptions = defs;
650
651 ret = set_defaults(defs);
652
653 if (ret != NSERROR_OK) {
654 nsoptions = opts;
655 nsoption_free(defs);
656 return ret;
657 }
658 }
659
660 /* copy the default values into the working set */
661 ret = nsoption_dup(defs, &opts);
662 if (ret != NSERROR_OK) {
663 nsoption_free(defs);
664 return ret;
665 }
666
667 /* return values if wanted */
668 if (popts != NULL) {
669 *popts = opts;
670 } else {
671 nsoptions = opts;
672 }
673
674 if (pdefs != NULL) {
675 *pdefs = defs;
676 } else {
677 nsoptions_default = defs;
678 }
679
680 return NSERROR_OK;
681}
682
683/* exported interface documented in utils/nsoption.h */
685{
686 nserror res;
687
688 /* check to see if global table selected */
689 if (opts == NULL) {
691 if (res == NSERROR_OK) {
692 nsoptions = NULL;
693 }
694 } else {
695 res = nsoption_free(opts);
696 }
697 if (res != NSERROR_OK) {
698 return res;
699 }
700
701 /* check to see if global table selected */
702 if (defs == NULL) {
704 if (res == NSERROR_OK) {
705 nsoptions_default = NULL;
706 }
707 } else {
708 res = nsoption_free(defs);
709 }
710
711 return res;
712}
713
714
715/* exported interface documented in utils/nsoption.h */
717nsoption_read(const char *path, struct nsoption_s *opts)
718{
720 FILE *fp;
721 struct nsoption_s *defs;
722
723 if (path == NULL) {
725 }
726
727 /* check to see if global table selected */
728 if (opts == NULL) {
729 opts = nsoptions;
730 }
731
732 /**
733 * @todo is this an API bug not being a parameter
734 */
735 defs = nsoptions_default;
736
737 if ((opts == NULL) || (defs == NULL)) {
739 }
740
741 fp = fopen(path, "r");
742 if (!fp) {
743 NSLOG(netsurf, INFO, "Failed to open file '%s'", path);
744 return NSERROR_NOT_FOUND;
745 }
746
747 NSLOG(netsurf, INFO, "Successfully opened '%s' for Options file", path);
748
749 while (fgets(s, NSOPTION_MAX_LINE_LEN, fp)) {
750 optionline(opts, s, strlen(s));
751 }
752
753 fclose(fp);
754
755 nsoption_validate(opts, defs);
756
757 return NSERROR_OK;
758}
759
760
761/* exported interface documented in utils/nsoption.h */
764 struct nsoption_s *opts,
765 struct nsoption_s *defs)
766{
767 FILE *fp;
768 nserror ret;
769
770 if (path == NULL) {
772 }
773
774 /* check to see if global table selected */
775 if (opts == NULL) {
776 opts = nsoptions;
777 }
778
779 /* check to see if global table selected */
780 if (defs == NULL) {
781 defs = nsoptions_default;
782 }
783
784 if ((opts == NULL) || (defs == NULL)) {
786 }
787
788 fp = fopen(path, "w");
789 if (!fp) {
790 NSLOG(netsurf, INFO, "failed to open file '%s' for writing",
791 path);
792 return NSERROR_NOT_FOUND;
793 }
794
795 ret = nsoption_output(fp, opts, defs, false);
796
797 fclose(fp);
798
799 return ret;
800}
801
802/* exported interface documented in utils/nsoption.h */
804nsoption_dump(FILE *outf, struct nsoption_s *opts)
805{
806 if (outf == NULL) {
808 }
809
810 /* check to see if global table selected and available */
811 if (opts == NULL) {
812 opts = nsoptions;
813 }
814 if (opts == NULL) {
816 }
817
818 return nsoption_output(outf, opts, NULL, true);
819}
820
821
822/* exported interface documented in utils/nsoption.h */
824nsoption_commandline(int *pargc, char **argv, struct nsoption_s *opts)
825{
826 char *arg;
827 char *val;
828 int arglen;
829 int idx = 1;
830 int mv_loop;
831 unsigned int entry_loop;
832
833 if ((pargc == NULL) || (argv == NULL)) {
835 }
836
837 /* check to see if global table selected and available */
838 if (opts == NULL) {
839 opts = nsoptions;
840 }
841 if (opts == NULL) {
843 }
844
845 while (idx < *pargc) {
846 arg = argv[idx];
847 arglen = strlen(arg);
848
849 /* check we have an option */
850 /* option must start -- and be as long as the shortest option*/
851 if ((arglen < (2+5) ) || (arg[0] != '-') || (arg[1] != '-'))
852 break;
853
854 arg += 2; /* skip -- */
855
856 val = strchr(arg, '=');
857 if (val == NULL) {
858 /* no equals sign - next parameter is val */
859 idx++;
860 if (idx >= *pargc)
861 break;
862 val = argv[idx];
863 } else {
864 /* equals sign */
865 arglen = val - arg ;
866 val++;
867 }
868
869 /* arg+arglen is the option to set, val is the value */
870
871 NSLOG(netsurf, INFO, "%.*s = %s", arglen, arg, val);
872
873 for (entry_loop = 0;
874 entry_loop < NSOPTION_LISTEND;
875 entry_loop++) {
876 if (strncmp(arg, opts[entry_loop].key, arglen) == 0) {
877 strtooption(val, opts + entry_loop);
878 break;
879 }
880 }
881
882 idx++;
883 }
884
885 /* remove processed options from argv */
886 for (mv_loop=0; mv_loop < (*pargc - idx); mv_loop++) {
887 argv[mv_loop + 1] = argv[mv_loop + idx];
888 }
889 *pargc -= (idx - 1);
890
892
893 return NSERROR_OK;
894}
895
896/* exported interface documented in options.h */
897int
899 size_t size,
900 enum nsoption_e option_idx,
901 const char *fmt)
902{
903 size_t slen = 0; /* current output string length */
904 int fmtc = 0; /* current index into format string */
905 struct nsoption_s *option;
906
907 if (fmt == NULL) {
908 return -1;
909 }
910
911 if (option_idx >= NSOPTION_LISTEND) {
912 return -1;
913 }
914
915 if (nsoptions == NULL) {
916 return -1;
917 }
918
919 option = &nsoptions[option_idx]; /* assume the global table */
920 if (option == NULL || option->key == NULL) {
921 return -1;
922 }
923
924 while ((slen < size) && (fmt[fmtc] != 0)) {
925 if (fmt[fmtc] == '%') {
926 fmtc++;
927 switch (fmt[fmtc]) {
928 case 'k':
929 slen += snprintf(string + slen,
930 size - slen,
931 "%s",
932 option->key);
933 break;
934
935 case 'p':
938 option_idx)) {
939 slen += snprintf(string + slen,
940 size - slen,
941 "user");
942 } else {
943 slen += snprintf(string + slen,
944 size - slen,
945 "default");
946 }
947 break;
948
949 case 't':
950 switch (option->type) {
951 case OPTION_BOOL:
952 slen += snprintf(string + slen,
953 size - slen,
954 "boolean");
955 break;
956
957 case OPTION_INTEGER:
958 slen += snprintf(string + slen,
959 size - slen,
960 "integer");
961 break;
962
963 case OPTION_UINT:
964 slen += snprintf(string + slen,
965 size - slen,
966 "unsigned integer");
967 break;
968
969 case OPTION_COLOUR:
970 slen += snprintf(string + slen,
971 size - slen,
972 "colour");
973 break;
974
975 case OPTION_STRING:
976 slen += snprintf(string + slen,
977 size - slen,
978 "string");
979 break;
980
981 }
982 break;
983
984
985 case 'V':
986 slen += nsoption_output_value_html(option,
987 size,
988 slen,
989 string);
990 break;
991 case 'v':
992 slen += nsoption_output_value_text(option,
993 size,
994 slen,
995 string);
996 break;
997 }
998 fmtc++;
999 } else {
1000 string[slen] = fmt[fmtc];
1001 slen++;
1002 fmtc++;
1003 }
1004 }
1005
1006 /* Ensure that we NUL-terminate the output */
1007 string[min(slen, size - 1)] = '\0';
1008
1009 return slen;
1010}
1011
1012/* exported interface documented in options.h */
1013nserror
1015 enum nsoption_e option_idx,
1016 char *s)
1017{
1018 struct nsoption_s *option;
1019
1020 option = &opts[option_idx];
1021
1022 /* ensure it is a string option */
1023 if (option->type != OPTION_STRING) {
1024 return NSERROR_BAD_PARAMETER;
1025 }
1026
1027 /* free any existing string */
1028 if (option->value.s != NULL) {
1029 free(option->value.s);
1030 }
1031
1032 option->value.s = s;
1033
1034 /* check for empty string */
1035 if ((option->value.s != NULL) && (*option->value.s == 0)) {
1036 free(option->value.s);
1037 option->value.s = NULL;
1038 }
1039 return NSERROR_OK;
1040}
static nserror set_defaults(struct nsoption_s *defaults)
Set option defaults for atari frontend.
Definition: gui.c:909
Option available on all platforms.
#define NSOPTION_SYS_COLOUR_END
Definition: options.h:38
#define NSOPTION_SYS_COLOUR_START
Definition: options.h:37
Error codes.
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_NOT_FOUND
Requested item not found.
Definition: errors.h:34
@ NSERROR_BAD_PARAMETER
Bad Parameter.
Definition: errors.h:48
@ NSERROR_INVALID
Invalid data.
Definition: errors.h:49
@ NSERROR_NOMEM
Memory exhaustion.
Definition: errors.h:32
@ NSERROR_OK
No error.
Definition: errors.h:30
const char * type
Definition: filetype.cpp:44
Option specific to RISC OS.
Netsurf additional integer type formatting macros.
nserror nslog_set_filter_by_options(void)
Set the logging filter according to the options.
Definition: log.c:289
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
plotter style interfaces, generic styles and style colour helpers.
#define colour_to_bw_furthest(c0)
Definition: plot_style.h:193
#define colour_rb_swap(c)
Definition: plot_style.h:217
Interface to utility string handling.
bool b
Definition: nsoption.h:115
const char * key
Definition: nsoption.h:111
union nsoption_s::@149 value
enum nsoption_type_e type
Definition: nsoption.h:113
colour c
Definition: nsoption.h:120
unsigned int u
Definition: nsoption.h:117
char * s
Definition: nsoption.h:118
uint32_t colour
Colour type: XBGR.
Definition: types.h:35
struct nsoption_s * nsoptions_default
global default option table.
Definition: nsoption.c:46
static bool strtooption(const char *value, struct nsoption_s *option)
Set an option value based on a string.
Definition: nsoption.c:97
#define NSOPTION_MAX_LINE_LEN
Length of buffer used to read lines from input file.
Definition: nsoption.c:43
static nserror nsoption_output(FILE *fp, struct nsoption_s *opts, struct nsoption_s *defs, bool all)
Output choices to file stream.
Definition: nsoption.c:289
static size_t nsoption_output_value_html(struct nsoption_s *option, size_t size, size_t pos, char *string)
Output an option value into a string, in HTML format.
Definition: nsoption.c:356
static nserror nsoption_dup(struct nsoption_s *src, struct nsoption_s **pdst)
Duplicates an option table.
Definition: nsoption.c:489
int nsoption_snoptionf(char *string, size_t size, enum nsoption_e option_idx, const char *fmt)
Fill a buffer with an option using a format.
Definition: nsoption.c:898
static bool nsoption_is_set(const struct nsoption_s *opts, const struct nsoption_s *defs, const enum nsoption_e entry)
Determines if an option is different between two option tables.
Definition: nsoption.c:227
static nserror optionline(struct nsoption_s *opts, char *line, int linelen)
Process a line from a user option file.
Definition: nsoption.c:603
nserror nsoption_set_tbl_charp(struct nsoption_s *opts, enum nsoption_e option_idx, char *s)
Set string option in specified table.
Definition: nsoption.c:1014
static struct nsoption_s defaults[]
The table of compiled in default options.
Definition: nsoption.c:64
static void nsoption_validate(struct nsoption_s *opts, struct nsoption_s *defs)
Definition: nsoption.c:145
nserror nsoption_dump(FILE *outf, struct nsoption_s *opts)
Write all options to a stream.
Definition: nsoption.c:804
nserror nsoption_read(const char *path, struct nsoption_s *opts)
Read choices file and set them in the passed table.
Definition: nsoption.c:717
struct nsoption_s * nsoptions
global active option table.
Definition: nsoption.c:45
static nserror nsoption_free(struct nsoption_s *opts)
frees an option table.
Definition: nsoption.c:522
nserror nsoption_commandline(int *pargc, char **argv, struct nsoption_s *opts)
Process commandline and set options approriately.
Definition: nsoption.c:824
nserror nsoption_init(nsoption_set_default_t *set_defaults, struct nsoption_s **popts, struct nsoption_s **pdefs)
Initialise option system.
Definition: nsoption.c:629
nserror nsoption_write(const char *path, struct nsoption_s *opts, struct nsoption_s *defs)
Write options that have changed from the defaults to a file.
Definition: nsoption.c:763
nserror nsoption_finalise(struct nsoption_s *opts, struct nsoption_s *defs)
Finalise option system.
Definition: nsoption.c:684
static nserror get_key_value(char *line, int linelen, char **key_out, char **value_out)
extract key/value from a line of input
Definition: nsoption.c:552
static size_t nsoption_output_value_text(struct nsoption_s *option, size_t size, size_t pos, char *string)
Output an option value into a string, in plain text format.
Definition: nsoption.c:429
Option reading and saving interface.
nsoption_e
Definition: nsoption.h:131
@ NSOPTION_LISTEND
Definition: nsoption.h:150
nserror() nsoption_set_default_t(struct nsoption_s *defaults)
default setting callback.
Definition: nsoption.h:172
@ OPTION_STRING
option is a heap allocated string.
Definition: nsoption.h:106
@ OPTION_COLOUR
Option is a netsurf colour.
Definition: nsoption.h:107
@ OPTION_UINT
Option is an unsigned integer.
Definition: nsoption.h:105
@ OPTION_INTEGER
Option is an integer.
Definition: nsoption.h:104
@ OPTION_BOOL
Option is a boolean.
Definition: nsoption.h:103
Interface to a number of general purpose functionality.
#define min(x, y)
Definition: utils.h:46
static nserror path(const struct redraw_context *ctx, const plot_style_t *pstyle, const float *p, unsigned int n, const float transform[6])
Plots a path.
Definition: plot.c:821
static nserror line(const struct redraw_context *ctx, const plot_style_t *style, const struct rect *line)
Plots a line.
Definition: plot.c:579