1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * GimpConfig object property dumper.
5 * Copyright (C) 2001-2006 Sven Neumann <sven@gimp.org>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <cairo.h>
27 #include <gegl.h>
28 #include <gdk-pixbuf/gdk-pixbuf.h>
29
30 #ifdef G_OS_WIN32
31 #include <gio/gwin32outputstream.h>
32 #else
33 #include <gio/gunixoutputstream.h>
34 #endif
35
36 #include "libgimpbase/gimpbase.h"
37 #include "libgimpcolor/gimpcolor.h"
38 #include "libgimpconfig/gimpconfig.h"
39
40 #include "config-types.h"
41
42 #include "gimpconfig-dump.h"
43 #include "gimprc.h"
44
45
46
47 static void dump_gimprc_system (GimpConfig *rc,
48 GimpConfigWriter *writer,
49 GOutputStream *output);
50 static void dump_gimprc_manpage (GimpConfig *rc,
51 GimpConfigWriter *writer,
52 GOutputStream *output);
53 static gchar * dump_describe_param (GParamSpec *param_spec);
54 static void dump_with_linebreaks (GOutputStream *output,
55 const gchar *text);
56
57
58 gboolean
gimp_config_dump(GObject * gimp,GimpConfigDumpFormat format)59 gimp_config_dump (GObject *gimp,
60 GimpConfigDumpFormat format)
61 {
62 GOutputStream *output;
63 GimpConfigWriter *writer;
64 GimpConfig *rc;
65
66 g_return_val_if_fail (G_IS_OBJECT (gimp), FALSE);
67
68 rc = g_object_new (GIMP_TYPE_RC,
69 "gimp", gimp,
70 NULL);
71
72 #ifdef G_OS_WIN32
73 output = g_win32_output_stream_new ((gpointer) 1, FALSE);
74 #else
75 output = g_unix_output_stream_new (1, FALSE);
76 #endif
77
78 writer = gimp_config_writer_new_stream (output, NULL, NULL);
79
80 switch (format)
81 {
82 case GIMP_CONFIG_DUMP_NONE:
83 break;
84
85 case GIMP_CONFIG_DUMP_GIMPRC:
86 gimp_config_writer_comment (writer,
87 "Dump of the GIMP default configuration");
88 gimp_config_writer_linefeed (writer);
89 gimp_config_serialize_properties (rc, writer);
90 gimp_config_writer_linefeed (writer);
91 break;
92
93 case GIMP_CONFIG_DUMP_GIMPRC_SYSTEM:
94 dump_gimprc_system (rc, writer, output);
95 break;
96
97 case GIMP_CONFIG_DUMP_GIMPRC_MANPAGE:
98 dump_gimprc_manpage (rc, writer, output);
99 break;
100 }
101
102 gimp_config_writer_finish (writer, NULL, NULL);
103 g_object_unref (output);
104 g_object_unref (rc);
105
106 return TRUE;
107 }
108
109
110 static const gchar system_gimprc_header[] =
111 "This is the system-wide gimprc file. Any change made in this file "
112 "will affect all users of this system, provided that they are not "
113 "overriding the default values in their personal gimprc file.\n"
114 "\n"
115 "Lines that start with a '#' are comments. Blank lines are ignored.\n"
116 "\n"
117 "By default everything in this file is commented out. The file then "
118 "documents the default values and shows what changes are possible.\n"
119 "\n"
120 "The variable ${gimp_dir} is set to the value of the environment "
121 "variable GIMP2_DIRECTORY or, if that is not set, the compiled-in "
122 "default value is used. If GIMP2_DIRECTORY is not an absolute path, "
123 "it is interpreted relative to your home directory.";
124
125 static void
dump_gimprc_system(GimpConfig * rc,GimpConfigWriter * writer,GOutputStream * output)126 dump_gimprc_system (GimpConfig *rc,
127 GimpConfigWriter *writer,
128 GOutputStream *output)
129 {
130 GObjectClass *klass;
131 GParamSpec **property_specs;
132 guint n_property_specs;
133 guint i;
134
135 gimp_config_writer_comment (writer, system_gimprc_header);
136 gimp_config_writer_linefeed (writer);
137
138 klass = G_OBJECT_GET_CLASS (rc);
139 property_specs = g_object_class_list_properties (klass, &n_property_specs);
140
141 for (i = 0; i < n_property_specs; i++)
142 {
143 GParamSpec *prop_spec = property_specs[i];
144 gchar *comment;
145
146 if (! (prop_spec->flags & GIMP_CONFIG_PARAM_SERIALIZE))
147 continue;
148
149 if (prop_spec->flags & GIMP_CONFIG_PARAM_IGNORE)
150 continue;
151
152 comment = dump_describe_param (prop_spec);
153 if (comment)
154 {
155 gimp_config_writer_comment (writer, comment);
156 g_free (comment);
157 }
158
159 gimp_config_writer_comment_mode (writer, TRUE);
160 gimp_config_writer_linefeed (writer);
161
162 if (! strcmp (prop_spec->name, "num-processors"))
163 {
164 gimp_config_writer_open (writer, "num-processors");
165 gimp_config_writer_printf (writer, "1");
166 gimp_config_writer_close (writer);
167 }
168 else if (! strcmp (prop_spec->name, "tile-cache-size"))
169 {
170 gimp_config_writer_open (writer, "tile-cache-size");
171 gimp_config_writer_printf (writer, "2g");
172 gimp_config_writer_close (writer);
173 }
174 else if (! strcmp (prop_spec->name, "undo-size"))
175 {
176 gimp_config_writer_open (writer, "undo-size");
177 gimp_config_writer_printf (writer, "1g");
178 gimp_config_writer_close (writer);
179 }
180 else if (! strcmp (prop_spec->name, "mypaint-brush-path"))
181 {
182 gchar *path = g_strdup_printf ("@mypaint_brushes_dir@%s"
183 "~/.mypaint/brushes",
184 G_SEARCHPATH_SEPARATOR_S);
185
186 gimp_config_writer_open (writer, "mypaint-brush-path");
187 gimp_config_writer_string (writer, path);
188 gimp_config_writer_close (writer);
189
190 g_free (path);
191 }
192 else
193 {
194 gimp_config_serialize_property (rc, prop_spec, writer);
195 }
196
197 gimp_config_writer_comment_mode (writer, FALSE);
198 gimp_config_writer_linefeed (writer);
199 }
200
201 g_free (property_specs);
202 }
203
204
205 static const gchar man_page_header[] =
206 ".\\\" This man-page is auto-generated by gimp --dump-gimprc-manpage.\n"
207 "\n"
208 ".TH GIMPRC 5 \"Version @GIMP_VERSION@\" \"GIMP Manual Pages\"\n"
209 ".SH NAME\n"
210 "gimprc \\- gimp configuration file\n"
211 ".SH DESCRIPTION\n"
212 "The\n"
213 ".B gimprc\n"
214 "file is a configuration file read by GIMP when it starts up. There\n"
215 "are two of these: one system-wide one stored in\n"
216 "@gimpsysconfdir@/gimprc and a per-user @manpage_gimpdir@/gimprc\n"
217 "which may override system settings.\n"
218 "\n"
219 "Comments are introduced by a hash sign (#), and continue until the end\n"
220 "of the line. Blank lines are ignored.\n"
221 "\n"
222 "The\n"
223 ".B gimprc\n"
224 "file associates values with properties. These properties may be set\n"
225 "by lisp-like assignments of the form:\n"
226 ".IP\n"
227 "\\f3(\\f2property\\-name\\ value\\f3)\\f1\n"
228 ".TP\n"
229 "where:\n"
230 ".TP 10\n"
231 ".I property\\-name\n"
232 "is one of the property names described below.\n"
233 ".TP\n"
234 ".I value\n"
235 "is the value the property is to be set to.\n"
236 ".PP\n"
237 "\n"
238 "Either spaces or tabs may be used to separate the name from the value.\n"
239 ".PP\n"
240 ".SH PROPERTIES\n"
241 "Valid properties and their default values are:\n"
242 "\n";
243
244 static const gchar *man_page_path =
245 ".PP\n"
246 ".SH PATH EXPANSION\n"
247 "Strings of type PATH are expanded in a manner similar to\n"
248 ".BR bash (1).\n"
249 "Specifically: tilde (~) is expanded to the user's home directory. Note that\n"
250 "the bash feature of being able to refer to other user's home directories\n"
251 "by writing ~userid/ is not valid in this file.\n"
252 "\n"
253 "${variable} is expanded to the current value of an environment variable.\n"
254 "There are a few variables that are pre-defined:\n"
255 ".TP\n"
256 ".I gimp_dir\n"
257 "The personal gimp directory which is set to the value of the environment\n"
258 "variable GIMP2_DIRECTORY or to @manpage_gimpdir@.\n"
259 ".TP\n"
260 ".I gimp_data_dir\n"
261 "Base for paths to shareable data, which is set to the value of the\n"
262 "environment variable GIMP2_DATADIR or to the compiled-in default value\n"
263 "@gimpdatadir@.\n"
264 ".TP\n"
265 ".I gimp_plug_in_dir\n"
266 "Base to paths for architecture-specific plug-ins and modules, which is set\n"
267 "to the value of the environment variable GIMP2_PLUGINDIR or to the\n"
268 "compiled-in default value @gimpplugindir@.\n"
269 ".TP\n"
270 ".I gimp_sysconf_dir\n"
271 "Path to configuration files, which is set to the value of the environment\n"
272 "variable GIMP2_SYSCONFDIR or to the compiled-in default value \n"
273 "@gimpsysconfdir@.\n"
274 ".TP\n"
275 ".I gimp_cache_dir\n"
276 "Path to cached files, which is set to the value of the environment\n"
277 "variable GIMP2_CACHEDIR or to the system default for per-user cached files.\n"
278 ".TP\n"
279 ".I gimp_temp_dir\n"
280 "Path to temporary files, which is set to the value of the environment\n"
281 "variable GIMP2_TEMPDIR or to the system default for temporary files.\n"
282 "\n";
283
284 static const gchar man_page_footer[] =
285 ".SH FILES\n"
286 ".TP\n"
287 ".I @gimpsysconfdir@/gimprc\n"
288 "System-wide configuration file\n"
289 ".TP\n"
290 ".I @manpage_gimpdir@/gimprc\n"
291 "Per-user configuration file\n"
292 "\n"
293 ".SH \"SEE ALSO\"\n"
294 ".BR gimp (1)\n";
295
296
297 static void
dump_gimprc_manpage(GimpConfig * rc,GimpConfigWriter * writer,GOutputStream * output)298 dump_gimprc_manpage (GimpConfig *rc,
299 GimpConfigWriter *writer,
300 GOutputStream *output)
301 {
302 GObjectClass *klass;
303 GParamSpec **property_specs;
304 guint n_property_specs;
305 guint i;
306
307 g_output_stream_printf (output, NULL, NULL, NULL,
308 "%s", man_page_header);
309
310 klass = G_OBJECT_GET_CLASS (rc);
311 property_specs = g_object_class_list_properties (klass, &n_property_specs);
312
313 for (i = 0; i < n_property_specs; i++)
314 {
315 GParamSpec *prop_spec = property_specs[i];
316 gchar *desc;
317 gboolean success;
318
319 if (! (prop_spec->flags & GIMP_CONFIG_PARAM_SERIALIZE))
320 continue;
321
322 if (prop_spec->flags & GIMP_CONFIG_PARAM_IGNORE)
323 continue;
324
325 g_output_stream_printf (output, NULL, NULL, NULL,
326 ".TP\n");
327
328 if (! strcmp (prop_spec->name, "num-processors"))
329 {
330 gimp_config_writer_open (writer, "num-processors");
331 gimp_config_writer_printf (writer, "1");
332 gimp_config_writer_close (writer);
333
334 success = TRUE;
335 }
336 else if (! strcmp (prop_spec->name, "tile-cache-size"))
337 {
338 gimp_config_writer_open (writer, "tile-cache-size");
339 gimp_config_writer_printf (writer, "2g");
340 gimp_config_writer_close (writer);
341
342 success = TRUE;
343 }
344 else if (! strcmp (prop_spec->name, "undo-size"))
345 {
346 gimp_config_writer_open (writer, "undo-size");
347 gimp_config_writer_printf (writer, "1g");
348 gimp_config_writer_close (writer);
349
350 success = TRUE;
351 }
352 else if (! strcmp (prop_spec->name, "mypaint-brush-path"))
353 {
354 gchar *path = g_strdup_printf ("@mypaint_brushes_dir@%s"
355 "~/.mypaint/brushes",
356 G_SEARCHPATH_SEPARATOR_S);
357
358 gimp_config_writer_open (writer, "mypaint-brush-path");
359 gimp_config_writer_string (writer, path);
360 gimp_config_writer_close (writer);
361
362 g_free (path);
363
364 success = TRUE;
365 }
366 else
367 {
368 success = gimp_config_serialize_property (rc, prop_spec, writer);
369 }
370
371 if (success)
372 {
373 g_output_stream_printf (output, NULL, NULL, NULL,
374 "\n");
375
376 desc = dump_describe_param (prop_spec);
377
378 dump_with_linebreaks (output, desc);
379
380 g_output_stream_printf (output, NULL, NULL, NULL,
381 "\n");
382
383 g_free (desc);
384 }
385 }
386
387 g_free (property_specs);
388
389 g_output_stream_printf (output, NULL, NULL, NULL,
390 "%s", man_page_path);
391 g_output_stream_printf (output, NULL, NULL, NULL,
392 "%s", man_page_footer);
393 }
394
395
396 static const gchar display_format_description[] =
397 "This is a format string; certain % character sequences are recognised and "
398 "expanded as follows:\n"
399 "\n"
400 "%% literal percent sign\n"
401 "%f bare filename, or \"Untitled\"\n"
402 "%F full path to file, or \"Untitled\"\n"
403 "%p PDB image id\n"
404 "%i view instance number\n"
405 "%t image type (RGB, grayscale, indexed)\n"
406 "%z zoom factor as a percentage\n"
407 "%s source scale factor\n"
408 "%d destination scale factor\n"
409 "%Dx expands to x if the image is dirty, the empty string otherwise\n"
410 "%Cx expands to x if the image is clean, the empty string otherwise\n"
411 "%B expands to (modified) if the image is dirty, the empty string otherwise\n"
412 "%A expands to (clean) if the image is clean, the empty string otherwise\n"
413 "%Nx expands to x if the image is export-dirty, the empty string otherwise\n"
414 "%Ex expands to x if the image is export-clean, the empty string otherwise\n"
415 "%l the number of layers\n"
416 "%L the number of layers (long form)\n"
417 "%m memory used by the image\n"
418 "%n the name of the active layer/channel\n"
419 "%P the PDB id of the active layer/channel\n"
420 "%w image width in pixels\n"
421 "%W image width in real-world units\n"
422 "%h image height in pixels\n"
423 "%H image height in real-world units\n"
424 "%M the image size expressed in megapixels\n"
425 "%u unit symbol\n"
426 "%U unit abbreviation\n"
427 "%x the width of the active layer/channel in pixels\n"
428 "%X the width of the active layer/channel in real-world units\n"
429 "%y the height of the active layer/channel in pixels\n"
430 "%Y the height of the active layer/channel in real-world units\n"
431 "%o the name of the image's color profile\n\n";
432
433
434 static gchar *
dump_describe_param(GParamSpec * param_spec)435 dump_describe_param (GParamSpec *param_spec)
436 {
437 const gchar *blurb = g_param_spec_get_blurb (param_spec);
438 const gchar *values = NULL;
439
440 if (!blurb)
441 {
442 g_warning ("FIXME: Property '%s' has no blurb.", param_spec->name);
443
444 blurb = g_strdup_printf ("The %s property has no description.",
445 param_spec->name);
446 }
447
448 if (GIMP_IS_PARAM_SPEC_RGB (param_spec))
449 {
450 if (gimp_param_spec_rgb_has_alpha (param_spec))
451 values =
452 "The color is specified in the form (color-rgba red green blue "
453 "alpha) with channel values as floats in the range of 0.0 to 1.0.";
454 else
455 values =
456 "The color is specified in the form (color-rgb red green blue) "
457 "with channel values as floats in the range of 0.0 to 1.0.";
458 }
459 else if (GIMP_IS_PARAM_SPEC_MEMSIZE (param_spec))
460 {
461 values =
462 "The integer size can contain a suffix of 'B', 'K', 'M' or 'G' which "
463 "makes GIMP interpret the size as being specified in bytes, kilobytes, "
464 "megabytes or gigabytes. If no suffix is specified the size defaults "
465 "to being specified in kilobytes.";
466 }
467 else if (GIMP_IS_PARAM_SPEC_CONFIG_PATH (param_spec))
468 {
469 switch (gimp_param_spec_config_path_type (param_spec))
470 {
471 case GIMP_CONFIG_PATH_FILE:
472 values = "This is a single filename.";
473 break;
474
475 case GIMP_CONFIG_PATH_FILE_LIST:
476 switch (G_SEARCHPATH_SEPARATOR)
477 {
478 case ':':
479 values = "This is a colon-separated list of files.";
480 break;
481 case ';':
482 values = "This is a semicolon-separated list of files.";
483 break;
484 default:
485 g_warning ("unhandled G_SEARCHPATH_SEPARATOR value");
486 break;
487 }
488 break;
489
490 case GIMP_CONFIG_PATH_DIR:
491 values = "This is a single folder.";
492 break;
493
494 case GIMP_CONFIG_PATH_DIR_LIST:
495 switch (G_SEARCHPATH_SEPARATOR)
496 {
497 case ':':
498 values = "This is a colon-separated list of folders to search.";
499 break;
500 case ';':
501 values = "This is a semicolon-separated list of folders to search.";
502 break;
503 default:
504 g_warning ("unhandled G_SEARCHPATH_SEPARATOR value");
505 break;
506 }
507 break;
508 }
509 }
510 else if (GIMP_IS_PARAM_SPEC_UNIT (param_spec))
511 {
512 values =
513 "The unit can be one inches, millimeters, points or picas plus "
514 "those in your user units database.";
515 }
516 else if (g_type_is_a (param_spec->value_type, GIMP_TYPE_CONFIG))
517 {
518 values = "This is a parameter list.";
519 }
520 else
521 {
522 switch (G_TYPE_FUNDAMENTAL (param_spec->value_type))
523 {
524 case G_TYPE_BOOLEAN:
525 values = "Possible values are yes and no.";
526 break;
527 case G_TYPE_INT:
528 case G_TYPE_UINT:
529 case G_TYPE_LONG:
530 case G_TYPE_ULONG:
531 values = "This is an integer value.";
532 break;
533 case G_TYPE_FLOAT:
534 case G_TYPE_DOUBLE:
535 values = "This is a float value.";
536 break;
537 case G_TYPE_STRING:
538 /* eek */
539 if (strcmp (g_param_spec_get_name (param_spec), "image-title-format")
540 &&
541 strcmp (g_param_spec_get_name (param_spec), "image-status-format"))
542 {
543 values = "This is a string value.";
544 }
545 else
546 {
547 values = display_format_description;
548 }
549 break;
550 case G_TYPE_ENUM:
551 {
552 GEnumClass *enum_class;
553 GEnumValue *enum_value;
554 GString *str;
555 gint i;
556
557 enum_class = g_type_class_peek (param_spec->value_type);
558
559 str = g_string_new (blurb);
560
561 g_string_append (str, " Possible values are ");
562
563 for (i = 0, enum_value = enum_class->values;
564 i < enum_class->n_values;
565 i++, enum_value++)
566 {
567 g_string_append (str, enum_value->value_nick);
568
569 switch (enum_class->n_values - i)
570 {
571 case 1:
572 g_string_append_c (str, '.');
573 break;
574 case 2:
575 g_string_append (str, " and ");
576 break;
577 default:
578 g_string_append (str, ", ");
579 break;
580 }
581 }
582
583 return g_string_free (str, FALSE);
584 }
585 break;
586 default:
587 break;
588 }
589 }
590
591 if (!values)
592 g_warning ("FIXME: Can't tell anything about a %s.",
593 g_type_name (param_spec->value_type));
594
595 if (strcmp (blurb, "") == 0)
596 return g_strdup_printf ("%s", values);
597 else
598 return g_strdup_printf ("%s %s", blurb, values);
599 }
600
601
602 #define LINE_LENGTH 78
603
604 static void
dump_with_linebreaks(GOutputStream * output,const gchar * text)605 dump_with_linebreaks (GOutputStream *output,
606 const gchar *text)
607 {
608 gint len = strlen (text);
609
610 while (len > 0)
611 {
612 const gchar *t;
613 gint i, space;
614
615 /* groff doesn't like lines to start with a single quote */
616 if (*text == '\'')
617 g_output_stream_printf (output, NULL, NULL, NULL,
618 "\\&"); /* a zero width space */
619
620 for (t = text, i = 0, space = 0;
621 *t != '\n' && (i <= LINE_LENGTH || space == 0) && i < len;
622 t++, i++)
623 {
624 if (g_ascii_isspace (*t))
625 space = i;
626 }
627
628 if (i > LINE_LENGTH && space && *t != '\n')
629 i = space;
630
631 g_output_stream_write_all (output, text, i, NULL, NULL, NULL);
632 g_output_stream_printf (output, NULL, NULL, NULL,
633 "\n");
634
635 if (*t == '\n')
636 g_output_stream_printf (output, NULL, NULL, NULL,
637 ".br\n");
638
639 i++;
640
641 text += i;
642 len -= i;
643 }
644 }
645