1 /* Watch stuff in the prefs workspace.
2  */
3 
4 /*
5 
6     Copyright (C) 1991-2003 The National Gallery
7 
8     This program is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation; either version 2 of the License, or
11     (at your watch) any later version.
12 
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17 
18     You should have received a copy of the GNU General Public License along
19     with this program; if not, write to the Free Software Foundation, Inc.,
20     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21 
22  */
23 
24 /*
25 
26     These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
27 
28  */
29 
30 /* Group watches with this.
31  */
32 
33 #define TYPE_WATCHGROUP (watchgroup_get_type())
34 #define WATCHGROUP( obj ) \
35 	(G_TYPE_CHECK_INSTANCE_CAST( (obj), TYPE_WATCHGROUP, Watchgroup ))
36 #define WATCHGROUP_CLASS( klass ) \
37 	(G_TYPE_CHECK_CLASS_CAST( (klass), TYPE_WATCHGROUP, WatchgroupClass))
38 #define IS_WATCHGROUP( obj ) \
39 	(G_TYPE_CHECK_INSTANCE_TYPE( (obj), TYPE_WATCHGROUP ))
40 #define IS_WATCHGROUP_CLASS( klass ) \
41 	(G_TYPE_CHECK_CLASS_TYPE( (klass), TYPE_WATCHGROUP ))
42 #define WATCHGROUP_GET_CLASS( obj ) \
43 	(G_TYPE_INSTANCE_GET_CLASS( (obj), TYPE_WATCHGROUP, WatchgroupClass ))
44 
45 typedef struct _Watchgroup {
46 	iContainer parent_object;
47 
48 	/* Workspaces we work within. Assume we are destroyed before this.
49 	 */
50 	Workspaceroot *workspaceroot;
51 
52 	/* Name of workspace our watchers check for their syms.
53 	 */
54 	const char *name;
55 
56 	/* Autosave timeout ... save our workspace automatically when this
57 	 * ticks away.
58 	 */
59 	guint auto_save_timeout;
60 } Watchgroup;
61 
62 typedef struct _WatchgroupClass {
63 	iContainerClass parent_class;
64 
65 	/* One of the watches in this group has changed.
66 	 * People interested in several watches can connect to
67 	 * this, rather than having to try listening for many "changed" signals
68 	 * on the watches.
69 	 */
70 	void (*watch_changed)( Watchgroup *, Watch * );
71 } WatchgroupClass;
72 
73 GType watchgroup_get_type( void );
74 Watchgroup *watchgroup_new( Workspaceroot *workspaceroot, const char *name );
75 void watchgroup_flush( Watchgroup *watchgroup );
76 
77 /* Abstract base class for something that watches a row.
78  */
79 
80 #define TYPE_WATCH (watch_get_type())
81 #define WATCH( obj ) \
82 	(G_TYPE_CHECK_INSTANCE_CAST( (obj), TYPE_WATCH, Watch ))
83 #define WATCH_CLASS( klass ) \
84 	(G_TYPE_CHECK_CLASS_CAST( (klass), TYPE_WATCH, WatchClass))
85 #define IS_WATCH( obj ) \
86 	(G_TYPE_CHECK_INSTANCE_TYPE( (obj), TYPE_WATCH ))
87 #define IS_WATCH_CLASS( klass ) \
88 	(G_TYPE_CHECK_CLASS_TYPE( (klass), TYPE_WATCH ))
89 #define WATCH_GET_CLASS( obj ) \
90 	(G_TYPE_INSTANCE_GET_CLASS( (obj), TYPE_WATCH, WatchClass ))
91 
92 typedef void (*WatchCallbackFn)( void * );
93 
94 struct _Watch {
95 	iContainer parent_class;
96 
97 	Row *row;			/* Row we watch */
98 	gboolean ok;			/* Value read OK on last change */
99 
100 	guint destroy_sid;		/* Listen for events */
101 	guint changed_sid;
102 };
103 
104 typedef struct _WatchClass {
105 	iContainerClass parent_class;
106 
107 	/* Update value from row.
108 	 */
109 	gboolean (*update)( Watch * );
110 
111 	/* Get a pointer to value.
112 	 */
113 	void *(*get_value)( Watch * );
114 } WatchClass;
115 
116 Watch *watch_find( Watchgroup *watchgroup, const char *name );
117 GtkType watch_get_type( void );
118 void watch_relink_all( void );
119 void watch_vset( Watch *watch, const char *fmt, va_list args );
120 void watch_set( Watch *watch, const char *fmt, ... )
121 	__attribute__((format(printf, 2, 3)));
122 
123 /* A watch that watches something with an int value.
124  */
125 
126 typedef struct _WatchInt WatchInt;
127 
128 #define TYPE_WATCH_INT (watch_int_get_type())
129 #define WATCH_INT( obj ) \
130 	(G_TYPE_CHECK_INSTANCE_CAST( (obj), TYPE_WATCH_INT, WatchInt ))
131 #define WATCH_INT_CLASS( klass ) \
132 	(G_TYPE_CHECK_CLASS_CAST( (klass), TYPE_WATCH_INT, WatchIntClass))
133 #define IS_WATCH_INT( obj ) \
134 	(G_TYPE_CHECK_INSTANCE_TYPE( (obj), TYPE_WATCH_INT ))
135 #define IS_WATCH_INT_CLASS( klass ) \
136 	(G_TYPE_CHECK_CLASS_TYPE( (klass), TYPE_WATCH_INT ))
137 #define WATCH_INT_GET_CLASS( obj ) \
138 	(G_TYPE_INSTANCE_GET_CLASS( (obj), TYPE_WATCH_INT, WatchIntClass ))
139 
140 struct _WatchInt {
141 	Watch parent_class;
142 
143 	int value;
144 };
145 
146 typedef struct _WatchIntClass {
147 	WatchClass parent_class;
148 
149 } WatchIntClass;
150 
151 GtkType watch_int_get_type( void );
152 int watch_int_get( Watchgroup *, const char *name, int fallback );
153 
154 /* A watch that watches something with a double value.
155  */
156 
157 typedef struct _WatchDouble WatchDouble;
158 
159 #define TYPE_WATCH_DOUBLE (watch_double_get_type())
160 #define WATCH_DOUBLE( obj ) \
161 	(G_TYPE_CHECK_INSTANCE_CAST( (obj), TYPE_WATCH_DOUBLE, WatchDouble ))
162 #define WATCH_DOUBLE_CLASS( klass ) \
163 	(G_TYPE_CHECK_CLASS_CAST( (klass), TYPE_WATCH_DOUBLE, WatchDoubleClass))
164 #define IS_WATCH_DOUBLE( obj ) \
165 	(G_TYPE_CHECK_INSTANCE_TYPE( (obj), TYPE_WATCH_DOUBLE ))
166 #define IS_WATCH_DOUBLE_CLASS( klass ) \
167 	(G_TYPE_CHECK_CLASS_TYPE( (klass), TYPE_WATCH_DOUBLE ))
168 #define WATCH_DOUBLE_GET_CLASS( obj ) \
169 	(G_TYPE_INSTANCE_GET_CLASS( (obj), TYPE_WATCH_DOUBLE, \
170 		WatchDoubleClass ))
171 
172 struct _WatchDouble {
173 	Watch parent_class;
174 
175 	double value;
176 };
177 
178 typedef struct _WatchDoubleClass {
179 	WatchClass parent_class;
180 
181 } WatchDoubleClass;
182 
183 GtkType watch_double_get_type( void );
184 double watch_double_get( Watchgroup *, const char *name, double fallback );
185 
186 /* A watch that watches a path.
187  */
188 
189 typedef struct _WatchPath WatchPath;
190 
191 #define TYPE_WATCH_PATH (watch_path_get_type())
192 #define WATCH_PATH( obj ) \
193 	(G_TYPE_CHECK_INSTANCE_CAST( (obj), TYPE_WATCH_PATH, WatchPath ))
194 #define WATCH_PATH_CLASS( klass ) \
195 	(G_TYPE_CHECK_CLASS_CAST( (klass), TYPE_WATCH_PATH, WatchPathClass))
196 #define IS_WATCH_PATH( obj ) \
197 	(G_TYPE_CHECK_INSTANCE_TYPE( (obj), TYPE_WATCH_PATH ))
198 #define IS_WATCH_PATH_CLASS( klass ) \
199 	(G_TYPE_CHECK_CLASS_TYPE( (klass), TYPE_WATCH_PATH ))
200 #define WATCH_PATH_GET_CLASS( obj ) \
201 	(G_TYPE_INSTANCE_GET_CLASS( (obj), TYPE_WATCH_PATH, WatchPathClass ))
202 
203 struct _WatchPath {
204 	Watch parent_class;
205 
206 	GSList *value;
207 };
208 
209 typedef struct _WatchPathClass {
210 	WatchClass parent_class;
211 
212 } WatchPathClass;
213 
214 GtkType watch_path_get_type( void );
215 GSList *watch_path_get( Watchgroup *, const char *name, GSList *fallback );
216 
217 typedef struct _WatchBool WatchBool;
218 
219 #define TYPE_WATCH_BOOL (watch_bool_get_type())
220 #define WATCH_BOOL( obj ) \
221 	(G_TYPE_CHECK_INSTANCE_CAST( (obj), TYPE_WATCH_BOOL, WatchBool ))
222 #define WATCH_BOOL_CLASS( klass ) \
223 	(G_TYPE_CHECK_CLASS_CAST( (klass), TYPE_WATCH_BOOL, WatchBoolClass))
224 #define IS_WATCH_BOOL( obj ) \
225 	(G_TYPE_CHECK_INSTANCE_TYPE( (obj), TYPE_WATCH_BOOL ))
226 #define IS_WATCH_BOOL_CLASS( klass ) \
227 	(G_TYPE_CHECK_CLASS_TYPE( (klass), TYPE_WATCH_BOOL ))
228 #define WATCH_BOOL_GET_CLASS( obj ) \
229 	(G_TYPE_INSTANCE_GET_CLASS( (obj), TYPE_WATCH_BOOL, WatchBoolClass ))
230 
231 struct _WatchBool {
232 	Watch parent_class;
233 
234 	gboolean value;
235 };
236 
237 typedef struct _WatchBoolClass {
238 	WatchClass parent_class;
239 
240 } WatchBoolClass;
241 
242 GtkType watch_bool_get_type( void );
243 gboolean watch_bool_get( Watchgroup *, const char *name, gboolean fallback );
244 
245 typedef struct _WatchString WatchString;
246 
247 #define TYPE_WATCH_STRING (watch_string_get_type())
248 #define WATCH_STRING( obj ) \
249 	(G_TYPE_CHECK_INSTANCE_CAST( (obj), TYPE_WATCH_STRING, WatchString ))
250 #define WATCH_STRING_CLASS( klass ) \
251 	(G_TYPE_CHECK_CLASS_CAST( (klass), TYPE_WATCH_STRING, WatchStringClass))
252 #define IS_WATCH_STRING( obj ) \
253 	(G_TYPE_CHECK_INSTANCE_TYPE( (obj), TYPE_WATCH_STRING ))
254 #define IS_WATCH_STRING_CLASS( klass ) \
255 	(G_TYPE_CHECK_CLASS_TYPE( (klass), TYPE_WATCH_STRING ))
256 #define WATCH_STRING_GET_CLASS( obj ) \
257 	(G_TYPE_INSTANCE_GET_CLASS( (obj), TYPE_WATCH_STRING, \
258 		WatchStringClass ))
259 
260 struct _WatchString {
261 	Watch parent_class;
262 
263 	char *value;
264 };
265 
266 typedef struct _WatchStringClass {
267 	WatchClass parent_class;
268 
269 } WatchStringClass;
270 
271 GtkType watch_string_get_type( void );
272 const char *watch_string_get( Watchgroup *,
273 	const char *name, const char *fallback );
274 
275 /* Prefs we follow from C.
276  */
277 
278 /* Default show states.
279  */
280 #define DISPLAY_RULERS \
281 	(watch_bool_get( main_watchgroup, "DISPLAY_RULERS", FALSE ))
282 #define DISPLAY_STATUS \
283 	(watch_bool_get( main_watchgroup, "DISPLAY_STATUS", FALSE ))
284 #define DISPLAY_CONVERSION \
285 	(watch_bool_get( main_watchgroup, "DISPLAY_CONVERSION", FALSE ))
286 
287 /* Display a crosshair on image windows ... turn-off-able, since some desktop
288  * themes have almost invisible crosshairs.
289  */
290 #define DISPLAY_CROSSHAIR \
291 	(watch_bool_get( main_watchgroup, "DISPLAY_CROSSHAIR", TRUE ))
292 
293 /* Update children during paint.
294  */
295 #define PAINTBOX_RECOMP \
296 	(watch_bool_get( main_watchgroup, "PAINTBOX_RECOMP", TRUE ))
297 
298 /* Help browser.
299  */
300 #define BOX_BROWSER (watch_string_get( main_watchgroup, "BROWSER", "mozilla" ))
301 #define BOX_BROWSER_REMOTE (watch_string_get( main_watchgroup, \
302 	"BROWSER_REMOTE", "-remote 'openURL(%s)'" ))
303 
304 /* Thumbnail size.
305  */
306 #define DISPLAY_THUMBNAIL \
307 	(watch_int_get( main_watchgroup, "DISPLAY_THUMBNAIL", 64 ))
308 
309 /* High-quality thumbnails.
310  */
311 #define DISPLAY_THUMBNAIL_HQ \
312 	(watch_bool_get( main_watchgroup, "DISPLAY_THUMBNAIL_HQ", FALSE ))
313 
314 /* File stuff.
315  */
316 #define PIN_FILESEL \
317 	(watch_bool_get( main_watchgroup, "CALC_PIN_FILESEL", FALSE ))
318 #define IP_JPEG_Q \
319 	(watch_int_get( main_watchgroup, "JPEG_Q", 75 ))
320 #define IP_JPEG_ICC_PROFILE \
321 	(watch_int_get( main_watchgroup, "JPEG_ICC_PROFILE", 0 ))
322 #define IP_JPEG_ICC_PROFILE_FILE \
323 	(watch_string_get( main_watchgroup, "JPEG_ICC_PROFILE_FILE", \
324 		"$VIPSHOME/share/nip2/data/sRGB.icm" ))
325 #define IP_PPM_MODE \
326 	(watch_int_get( main_watchgroup, "PPM_MODE", 0 ))
327 #define IP_CSV_SEPARATOR \
328 	(watch_string_get( main_watchgroup, "CSV_SEPARATOR", "\t" ))
329 #define IP_PNG_COMPRESSION \
330 	(watch_int_get( main_watchgroup, "PNG_COMPRESSION", 6 ))
331 #define IP_PNG_INTERLACE \
332 	(watch_int_get( main_watchgroup, "PNG_INTERLACE", 0 ))
333 #define IP_TIFF_COMPRESSION \
334 	(watch_int_get( main_watchgroup, "TIFF_COMPRESSION", 0 ))
335 #define IP_TIFF_JPEG_Q \
336 	(watch_int_get( main_watchgroup, "TIFF_JPEG_Q", 75 ))
337 #define IP_TIFF_LAYOUT \
338 	(watch_int_get( main_watchgroup, "TIFF_LAYOUT", 0 ))
339 #define IP_TIFF_TILE_WIDTH \
340 	(watch_int_get( main_watchgroup, "TIFF_TILE_WIDTH", 128 ))
341 #define IP_TIFF_TILE_HEIGHT \
342 	(watch_int_get( main_watchgroup, "TIFF_TILE_HEIGHT", 128 ))
343 #define IP_TIFF_MULTI_RES \
344 	(watch_int_get( main_watchgroup, "TIFF_MULTI_RES", 0 ))
345 #define IP_TIFF_FORMAT \
346 	(watch_int_get( main_watchgroup, "TIFF_FORMAT", 0 ))
347 #define IP_TIFF_PREDICTOR \
348 	(watch_int_get( main_watchgroup, "TIFF_PREDICTOR", 0 ))
349 #define IP_TIFF_BIGTIFF \
350 	(watch_bool_get( main_watchgroup, "TIFF_BIGTIFF", FALSE ))
351 
352 /* Autoreload.
353  */
354 #define CALC_RELOAD (watch_bool_get( main_watchgroup, "CALC_RELOAD", FALSE ))
355 
356 /* Max chars we print.
357  */
358 #define LINELENGTH \
359 	IM_CLIP( 10, \
360 		watch_int_get( main_watchgroup, "CALC_LINELENGTH", 80 ), \
361 		MAX_LINELENGTH )
362 
363 /* CPUs we work over.
364  */
365 #define VIPS_CPUS \
366 	(watch_int_get( main_watchgroup, "VIPS_CPUS", 1 ))
367 
368 /* Bar prefs.
369  */
370 #define MAINW_TOOLBAR \
371 	(watch_bool_get( main_watchgroup, "MAINW_TOOLBAR", TRUE ))
372 #define MAINW_TOOLBAR_STYLE \
373 	(watch_int_get( main_watchgroup, "MAINW_TOOLBAR_STYLE", 0 ))
374 #define MAINW_STATUSBAR \
375 	(watch_bool_get( main_watchgroup, "MAINW_STATUSBAR", TRUE ))
376 
377 #define WORKSPACE_LPANE_OPEN \
378 	(watch_bool_get( main_watchgroup, "WORKSPACE_LPANE_OPEN", FALSE ))
379 #define WORKSPACE_LPANE_POSITION \
380 	(watch_int_get( main_watchgroup, "WORKSPACE_LPANE_POSITION", 200 ))
381 #define WORKSPACE_RPANE_OPEN \
382 	(watch_bool_get( main_watchgroup, "WORKSPACE_RPANE_OPEN", FALSE ))
383 #define WORKSPACE_RPANE_POSITION \
384 	(watch_int_get( main_watchgroup, "WORKSPACE_RPANE_POSITION", 400 ))
385 
386 /* Heap size. Big enough to always load prefs, small enough that it doesn't
387  * trash the computer.
388  */
389 #define MAX_HEAPSIZE \
390 	IM_CLIP( 100000, \
391 		watch_int_get( main_watchgroup, "CALC_MAX_HEAP", 200000 ), \
392 		10000000 )
393 
394 /* Region dragging.
395  */
396 #ifdef NO_UPDATE
397 #define CALC_RECOMP_REGION \
398 	(watch_bool_get( main_watchgroup, "CALC_RECOMP_REGION", FALSE ))
399 #else
400 #define CALC_RECOMP_REGION \
401 	(watch_bool_get( main_watchgroup, "CALC_RECOMP_REGION", TRUE ))
402 #endif
403 
404 /* Slider dragging.
405  */
406 #define CALC_RECOMP_SLIDER \
407 	(watch_bool_get( main_watchgroup, "CALC_RECOMP_SLIDER", FALSE ))
408 
409 /* Popup new objects.
410  */
411 #define POPUP_NEW_ROWS \
412 	(watch_bool_get( main_watchgroup, "POPUP_NEW_ROWS", FALSE ))
413 
414 /* Draw LEDs rather than recolouring tally buttons.
415  */
416 #define CALC_DISPLAY_LED \
417 	(watch_bool_get( main_watchgroup, "CALC_DISPLAY_LED", FALSE ))
418 
419 /* Number of vips calls to memoise.
420  */
421 #define CALL_HISTORY_MAX \
422 	(watch_int_get( main_watchgroup, "VIPS_HISTORY_MAX", 200 ))
423 
424 /* Auto save wses.
425  */
426 #define AUTO_WS_SAVE \
427 	(watch_bool_get( main_watchgroup, "CALC_AUTO_WS_SAVE", TRUE ))
428 
429 /* Image window geometry.
430  */
431 #define IMAGE_WINDOW_WIDTH \
432 	(watch_int_get( main_watchgroup, "IMAGE_WINDOW_WIDTH", 600 ))
433 #define IMAGE_WINDOW_HEIGHT \
434 	(watch_int_get( main_watchgroup, "IMAGE_WINDOW_HEIGHT", 650 ))
435 
436 /* Default font.
437  */
438 #define PAINTBOX_FONT \
439 	(watch_string_get( main_watchgroup, "PAINTBOX_FONT", "Sans 12" ))
440 
441 /* Max undo steps ... -1 == unlimited.
442  */
443 #define PAINTBOX_MAX_UNDO \
444 	(watch_int_get( main_watchgroup, "PAINTBOX_MAX_UNDO", -1 ))
445 
446 /* Default image file type.
447  */
448 #define IMAGE_FILE_TYPE \
449 	(watch_int_get( main_watchgroup, "IMAGE_FILE_TYPE", 0 ))
450 
451 /* Prefs we watch.
452  */
453 #define PATH_SEARCH (watch_path_get( main_watchgroup, "CALC_PATH_SEARCH", \
454 	path_search_default ))
455 #define PATH_START (watch_path_get( main_watchgroup, "CALC_PATH_START", \
456 	path_start_default ))
457 #define PATH_TMP (watch_string_get( main_watchgroup, "CALC_PATH_TMP", \
458 	path_tmp_default ))
459 
460 /* How we print stuff.
461  */
462 #define TRACE_FUNCTIONS \
463 	(watch_bool_get( main_watchgroup, "CALC_TRACE_FUNCTIONS", FALSE ))
464 #define PRINT_CARTESIAN \
465 	(watch_bool_get( main_watchgroup, "CALC_PRINT_CARTIESIAN", FALSE ))
466 
467 /* Program window.
468  */
469 #define PROGRAM_PANE_POSITION \
470 	(watch_double_get( main_watchgroup, "PROGRAM_PANE_POSITION", 200 ))
471 
472