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 /*
31 #define DEBUG
32 */
33
34 #include "ip.h"
35
36 static iContainerClass *watchgroup_parent_class = NULL;
37
38 /* Our signals.
39 */
40 enum {
41 SIG_WATCH_CHANGED, /* "changed" on one of our watches */
42 SIG_LAST
43 };
44
45 static guint watchgroup_signals[SIG_LAST] = { 0 };
46
47 static void
watchgroup_changed(Watchgroup * watchgroup,Watch * watch)48 watchgroup_changed( Watchgroup *watchgroup, Watch *watch )
49 {
50 g_signal_emit( G_OBJECT( watchgroup ),
51 watchgroup_signals[SIG_WATCH_CHANGED], 0, watch );
52 }
53
54 static void
watchgroup_class_init(WatchgroupClass * class)55 watchgroup_class_init( WatchgroupClass *class )
56 {
57 watchgroup_parent_class = g_type_class_peek_parent( class );
58
59 watchgroup_signals[SIG_WATCH_CHANGED] = g_signal_new( "watch_changed",
60 G_OBJECT_CLASS_TYPE( class ),
61 G_SIGNAL_RUN_FIRST,
62 G_STRUCT_OFFSET( WatchgroupClass, watch_changed ),
63 NULL, NULL,
64 g_cclosure_marshal_VOID__OBJECT,
65 G_TYPE_NONE, 1,
66 TYPE_WATCH );
67 }
68
69 static void
watchgroup_init(Watchgroup * watchgroup)70 watchgroup_init( Watchgroup *watchgroup )
71 {
72 #ifdef DEBUG
73 printf( "watchgroup_init\n" );
74 #endif /*DEBUG*/
75
76 watchgroup->auto_save_timeout = 0;
77 }
78
79 GType
watchgroup_get_type(void)80 watchgroup_get_type( void )
81 {
82 static GType watchgroup_type = 0;
83
84 if( !watchgroup_type ) {
85 static const GTypeInfo info = {
86 sizeof( WatchgroupClass ),
87 NULL, /* base_init */
88 NULL, /* base_finalize */
89 (GClassInitFunc) watchgroup_class_init,
90 NULL, /* class_finalize */
91 NULL, /* class_data */
92 sizeof( Watchgroup ),
93 32, /* n_preallocs */
94 (GInstanceInitFunc) watchgroup_init,
95 };
96
97 watchgroup_type = g_type_register_static( TYPE_ICONTAINER,
98 "Watchgroup", &info, 0 );
99 }
100
101 return( watchgroup_type );
102 }
103
104 Watchgroup *
watchgroup_new(Workspaceroot * workspaceroot,const char * name)105 watchgroup_new( Workspaceroot *workspaceroot, const char *name )
106 {
107 Watchgroup *watchgroup = WATCHGROUP(
108 g_object_new( TYPE_WATCHGROUP, NULL ) );
109
110 /* Assume it's a static string.
111 */
112 watchgroup->name = name;
113
114 watchgroup->workspaceroot = workspaceroot;
115 icontainer_set_hash( ICONTAINER( watchgroup ) );
116
117 return( watchgroup );
118 }
119
120 /* Get the ws we are storing prefs in, and check it looks OK.
121 */
122 static Workspace *
watchgroup_get_workspace(Watchgroup * watchgroup)123 watchgroup_get_workspace( Watchgroup *watchgroup )
124 {
125 Compile *compile;
126 Symbol *sym;
127
128 if( !watchgroup->workspaceroot->sym )
129 return( NULL );
130
131 compile = watchgroup->workspaceroot->sym->expr->compile;
132
133 if( !(sym = compile_lookup( compile, watchgroup->name )) ||
134 !sym->expr->compile ||
135 sym->type != SYM_WORKSPACE ||
136 !sym->ws )
137 return( NULL );
138
139 return( sym->ws );
140 }
141
142 static void
watchgroup_save(Watchgroup * watchgroup)143 watchgroup_save( Watchgroup *watchgroup )
144 {
145 Workspace *ws;
146
147 if( (ws = watchgroup_get_workspace( watchgroup )) ) {
148 Workspacegroup *wsg = workspace_get_workspacegroup( ws );
149 Filemodel *filemodel = FILEMODEL( wsg );
150
151 if( filemodel->modified ) {
152 symbol_recalculate_all();
153
154 /* Ignore error returns ... hmm! Tricky: we can come
155 * here during shutdown.
156 */
157 (void) filemodel_top_save( filemodel,
158 filemodel->filename );
159
160 filemodel_set_modified( filemodel, FALSE );
161 }
162 }
163 }
164
165 static gboolean
watchgroup_dirty_timeout_cb(Watchgroup * watchgroup)166 watchgroup_dirty_timeout_cb( Watchgroup *watchgroup )
167 {
168 watchgroup->auto_save_timeout = 0;
169
170 watchgroup_save( watchgroup );
171
172 return( FALSE );
173 }
174
175 void
watchgroup_dirty(Watchgroup * watchgroup)176 watchgroup_dirty( Watchgroup *watchgroup )
177 {
178 Workspace *ws;
179
180 /* Find the preferences workspace.
181 */
182 if( (ws = watchgroup_get_workspace( watchgroup )) ) {
183 Workspacegroup *wsg = workspace_get_workspacegroup( ws );
184
185 /* Mark ws dirty, start save timer.
186 */
187 filemodel_set_modified( FILEMODEL( wsg ), TRUE );
188
189 IM_FREEF( g_source_remove, watchgroup->auto_save_timeout );
190 watchgroup->auto_save_timeout = g_timeout_add( 1000,
191 (GSourceFunc) watchgroup_dirty_timeout_cb, watchgroup );
192 }
193 }
194
195 void
watchgroup_flush(Watchgroup * watchgroup)196 watchgroup_flush( Watchgroup *watchgroup )
197 {
198 /* Do we have a pending save?
199 */
200 if( watchgroup->auto_save_timeout ) {
201 watchgroup_save( watchgroup );
202
203 IM_FREEF( g_source_remove, watchgroup->auto_save_timeout );
204 }
205 }
206
207 static iContainerClass *watch_parent_class = NULL;
208 static GSList *watch_all = NULL;
209
210 static void
watch_finalize(GObject * gobject)211 watch_finalize( GObject *gobject )
212 {
213 Watch *watch;
214
215 g_return_if_fail( gobject != NULL );
216 g_return_if_fail( IS_WATCH( gobject ) );
217
218 watch = WATCH( gobject );
219
220 #ifdef DEBUG
221 printf( "watch_finalize: %s\n", NN( IOBJECT( watch )->name ) );
222 #endif /*DEBUG*/
223
224 watch_all = g_slist_remove( watch_all, watch );
225
226 G_OBJECT_CLASS( watch_parent_class )->finalize( gobject );
227 }
228
229 static void
watch_dispose(GObject * gobject)230 watch_dispose( GObject *gobject )
231 {
232 Watch *watch;
233
234 g_return_if_fail( gobject != NULL );
235 g_return_if_fail( IS_WATCH( gobject ) );
236
237 watch = WATCH( gobject );
238
239 #ifdef DEBUG
240 printf( "watch_dispose: %s\n", NN( IOBJECT( watch )->name ) );
241 #endif /*DEBUG*/
242
243 /* My instance destroy stuff.
244 */
245 FREESID( watch->destroy_sid, watch->row );
246 FREESID( watch->changed_sid, watch->row );
247 watch->row = NULL;
248
249 G_OBJECT_CLASS( watch_parent_class )->dispose( gobject );
250 }
251
252 static void
watch_changed(iObject * iobject)253 watch_changed( iObject *iobject )
254 {
255 Watch *watch = WATCH( iobject );
256 Watchgroup *watchgroup = WATCHGROUP( ICONTAINER( watch )->parent );
257
258 /* Emit on our group too. Can get here before our parent is linked on,
259 * careful.
260 */
261 if( watchgroup )
262 watchgroup_changed( WATCHGROUP( ICONTAINER( watch )->parent ),
263 watch );
264
265 IOBJECT_CLASS( watch_parent_class )->changed( iobject );
266 }
267
268 static void
watch_class_init(WatchClass * class)269 watch_class_init( WatchClass *class )
270 {
271 GObjectClass *gobject_class = (GObjectClass *) class;
272 iObjectClass *iobject_class = (iObjectClass *) class;
273 WatchClass *watch_class = (WatchClass *) class;
274
275 watch_parent_class = g_type_class_peek_parent( class );
276
277 gobject_class->finalize = watch_finalize;
278 gobject_class->dispose = watch_dispose;
279
280 iobject_class->changed = watch_changed;
281
282 watch_class->update = NULL;
283 watch_class->get_value = NULL;
284 }
285
286 static void
watch_init(Watch * watch)287 watch_init( Watch *watch )
288 {
289 watch->row = NULL;
290 watch->ok = FALSE;
291 watch->destroy_sid = 0;
292 watch->changed_sid = 0;
293
294 watch_all = g_slist_prepend( watch_all, watch );
295 }
296
297 GType
watch_get_type(void)298 watch_get_type( void )
299 {
300 static GType watch_type = 0;
301
302 if( !watch_type ) {
303 static const GTypeInfo info = {
304 sizeof( WatchClass ),
305 NULL, /* base_init */
306 NULL, /* base_finalize */
307 (GClassInitFunc) watch_class_init,
308 NULL, /* class_finalize */
309 NULL, /* class_data */
310 sizeof( Watch ),
311 32, /* n_preallocs */
312 (GInstanceInitFunc) watch_init,
313 };
314
315 watch_type = g_type_register_static( TYPE_ICONTAINER,
316 "Watch", &info, 0 );
317 }
318
319 return( watch_type );
320 }
321
322 static void
watch_link(Watch * watch,Watchgroup * watchgroup,const char * name)323 watch_link( Watch *watch, Watchgroup *watchgroup, const char *name )
324 {
325 iobject_set( IOBJECT( watch ), name, NULL );
326 icontainer_child_add( ICONTAINER( watchgroup ),
327 ICONTAINER( watch ), -1 );
328 }
329
330 static void
watch_destroy_cb(Row * row,Watch * watch)331 watch_destroy_cb( Row *row, Watch *watch )
332 {
333 #ifdef DEBUG
334 printf( "watch_destroy_cb\n" );
335 #endif /*DEBUG*/
336
337 watch->row = NULL;
338 watch->ok = FALSE;
339 watch->destroy_sid = 0;
340 watch->changed_sid = 0;
341 }
342
343 /* The row we are watching has changed.
344 */
345 static void
watch_changed_cb(Row * row,Watch * watch)346 watch_changed_cb( Row *row, Watch *watch )
347 {
348 #ifdef DEBUG
349 printf( "watch_changed_cb: %s\n", NN( IOBJECT( watch )->name ) );
350 #endif /*DEBUG*/
351
352 if( row->expr )
353 watch->ok = WATCH_GET_CLASS( watch )->update( watch );
354
355 iobject_changed( IOBJECT( watch ) );
356 }
357
358 /* Make sure we're linked to the thing we watch.
359 */
360 static void
watch_attach(Watch * watch)361 watch_attach( Watch *watch )
362 {
363 Watchgroup *watchgroup = WATCHGROUP( ICONTAINER( watch )->parent );
364 const char *name = IOBJECT( watch )->name;
365 Workspace *ws;
366 Symbol *sym;
367
368 if( watch->row )
369 return;
370
371 if( (ws = watchgroup_get_workspace( watchgroup )) &&
372 ws->sym->expr &&
373 ws->sym->expr->compile &&
374 (sym = compile_lookup( ws->sym->expr->compile, name )) &&
375 sym->expr->row ) {
376 watch->row = sym->expr->row;
377 watch->destroy_sid =
378 g_signal_connect( G_OBJECT( watch->row ), "destroy",
379 G_CALLBACK( watch_destroy_cb ), watch );
380 watch->changed_sid =
381 g_signal_connect( G_OBJECT( watch->row ), "changed",
382 G_CALLBACK( watch_changed_cb ), watch );
383 }
384 }
385
386 Watch *
watch_find(Watchgroup * watchgroup,const char * name)387 watch_find( Watchgroup *watchgroup, const char *name )
388 {
389 return( (Watch *)
390 (icontainer_child_lookup( ICONTAINER( watchgroup ), name )) );
391 }
392
393 static gboolean
watch_get(Watch * watch,void ** out)394 watch_get( Watch *watch, void **out )
395 {
396 #ifdef DEBUG
397 printf( "watch_get: %s\n", NN( IOBJECT( watch )->name ) );
398 #endif /*DEBUG*/
399
400 watch_attach( watch );
401
402 if( !watch->row )
403 return( FALSE );
404
405 if( !watch->ok )
406 watch->ok = WATCH_GET_CLASS( watch )->update( watch );
407
408 if( !watch->ok )
409 return( FALSE );
410
411 *out = WATCH_GET_CLASS( watch )->get_value( watch );
412
413 return( TRUE );
414 }
415
416 static void *
watch_relink(Watch * watch)417 watch_relink( Watch *watch )
418 {
419 if( !watch->row ) {
420 watch_attach( watch );
421 if( watch->row )
422 iobject_changed( IOBJECT( watch ) );
423 }
424
425 return( NULL );
426 }
427
428 void
watch_relink_all(void)429 watch_relink_all( void )
430 {
431 slist_map( watch_all, (SListMapFn) watch_relink, NULL );
432 }
433
434 void
watch_vset(Watch * watch,const char * fmt,va_list args)435 watch_vset( Watch *watch, const char *fmt, va_list args )
436 {
437 Watchgroup *watchgroup = WATCHGROUP( ICONTAINER( watch )->parent );
438
439 Workspace *ws;
440
441 /* In case we try to set after prefs has gone.
442 */
443 if( !(ws = watchgroup_get_workspace( watchgroup )) ||
444 ws->in_dispose )
445 return;
446
447 if( watch->row &&
448 watch->row->child_rhs &&
449 watch->row->child_rhs->itext ) {
450 iText *itext = ITEXT( watch->row->child_rhs->itext );
451 char buf[256];
452
453 (void) im_vsnprintf( buf, 256, fmt, args );
454
455 if( itext_set_formula( itext, buf ) ) {
456 #ifdef DEBUG
457 printf( "watch_vset: %s = %s\n",
458 IOBJECT( watch )->name, buf );
459 #endif /*DEBUG*/
460
461 itext_set_edited( itext, TRUE );
462 if( watch->row->sym )
463 expr_dirty( watch->row->sym->expr,
464 link_serial_new() );
465 watchgroup_dirty(
466 WATCHGROUP( ICONTAINER( watch )->parent ) );
467 }
468 }
469 }
470
471 void
watch_set(Watch * watch,const char * fmt,...)472 watch_set( Watch *watch, const char *fmt, ... )
473 {
474 va_list args;
475
476 va_start( args, fmt );
477 watch_vset( watch, fmt, args );
478 va_end( args );
479 }
480
481 static WatchClass *watch_double_parent_class = NULL;
482
483 static gboolean
watch_double_update(Watch * watch)484 watch_double_update( Watch *watch )
485 {
486 WatchDouble *watch_double = WATCH_DOUBLE( watch );
487 PElement *root = &watch->row->expr->root;
488
489 #ifdef DEBUG
490 printf( "watch_double_update\n" );
491 #endif /*DEBUG*/
492
493 if( PEISNOVAL( root ) )
494 return( FALSE );
495 if( !PEISREAL( root ) ) {
496 heap_error_typecheck( root, IOBJECT( watch )->name, "real" );
497 return( FALSE );
498 }
499
500 watch_double->value = PEGETREAL( root );
501
502 return( TRUE );
503 }
504
505 static void *
watch_double_get_value(Watch * watch)506 watch_double_get_value( Watch *watch )
507 {
508 WatchDouble *watch_double = WATCH_DOUBLE( watch );
509
510 return( (void *) &watch_double->value );
511 }
512
513 static void
watch_double_class_init(WatchDoubleClass * class)514 watch_double_class_init( WatchDoubleClass *class )
515 {
516 WatchClass *watch_class = (WatchClass *) class;
517
518 watch_double_parent_class = g_type_class_peek_parent( class );
519
520 watch_class->update = watch_double_update;
521 watch_class->get_value = watch_double_get_value;
522 }
523
524 static void
watch_double_init(WatchDouble * watch_double)525 watch_double_init( WatchDouble *watch_double )
526 {
527 #ifdef DEBUG
528 printf( "watch_double_init\n" );
529 #endif /*DEBUG*/
530
531 watch_double->value = -1.0;
532 }
533
534 GType
watch_double_get_type(void)535 watch_double_get_type( void )
536 {
537 static GType watch_double_type = 0;
538
539 if( !watch_double_type ) {
540 static const GTypeInfo info = {
541 sizeof( WatchDoubleClass ),
542 NULL, /* base_init */
543 NULL, /* base_finalize */
544 (GClassInitFunc) watch_double_class_init,
545 NULL, /* class_finalize */
546 NULL, /* class_data */
547 sizeof( WatchDouble ),
548 32, /* n_preallocs */
549 (GInstanceInitFunc) watch_double_init,
550 };
551
552 watch_double_type = g_type_register_static( TYPE_WATCH,
553 "WatchDouble", &info, 0 );
554 }
555
556 return( watch_double_type );
557 }
558
559 static Watch *
watch_double_new(Watchgroup * watchgroup,const char * name)560 watch_double_new( Watchgroup *watchgroup, const char *name )
561 {
562 WatchDouble *watch_double = WATCH_DOUBLE(
563 g_object_new( TYPE_WATCH_DOUBLE, NULL ) );
564
565 watch_link( WATCH( watch_double ), watchgroup, name );
566
567 return( WATCH( watch_double ) );
568 }
569
570 double
watch_double_get(Watchgroup * watchgroup,const char * name,double fallback)571 watch_double_get( Watchgroup *watchgroup, const char *name, double fallback )
572 {
573 Watch *watch;
574 void *value;
575
576 if( !watchgroup )
577 return( fallback );
578
579 if( !(watch = watch_find( watchgroup, name )) )
580 watch = watch_double_new( watchgroup, name );
581
582 g_assert( IS_WATCH_DOUBLE( watch ) );
583
584 if( !watch_get( watch, &value ) )
585 return( fallback );
586
587 return( *((double *) value) );
588 }
589
590 static WatchClass *watch_int_parent_class = NULL;
591
592 static gboolean
watch_int_update(Watch * watch)593 watch_int_update( Watch *watch )
594 {
595 WatchInt *watch_int = WATCH_INT( watch );
596 Expr *expr = watch->row->expr;
597 PElement *root;
598
599 #ifdef DEBUG
600 printf( "watch_int_update: %s\n", NN( IOBJECT( watch )->name ) );
601 #endif /*DEBUG*/
602
603 /* Can get called during shutdown :-( main_watchgroup_changed_cb() can
604 * call us before destroying the row, but after killing the expr.
605 */
606 if( !expr )
607 return( FALSE );
608 root = &expr->root;
609 if( PEISNOVAL( root ) )
610 return( FALSE );
611 if( !PEISREAL( root ) ) {
612 heap_error_typecheck( root, IOBJECT( watch )->name, "real" );
613 return( FALSE );
614 }
615
616 watch_int->value = IM_RINT( PEGETREAL( root ) );
617
618 return( TRUE );
619 }
620
621 static void *
watch_int_get_value(Watch * watch)622 watch_int_get_value( Watch *watch )
623 {
624 WatchInt *watch_int = WATCH_INT( watch );
625
626 return( (void *) &watch_int->value );
627 }
628
629 static void
watch_int_class_init(WatchIntClass * class)630 watch_int_class_init( WatchIntClass *class )
631 {
632 WatchClass *watch_class = (WatchClass *) class;
633
634 watch_int_parent_class = g_type_class_peek_parent( class );
635
636 watch_class->update = watch_int_update;
637 watch_class->get_value = watch_int_get_value;
638 }
639
640 static void
watch_int_init(WatchInt * watch_int)641 watch_int_init( WatchInt *watch_int )
642 {
643 #ifdef DEBUG
644 printf( "watch_int_init\n" );
645 #endif /*DEBUG*/
646
647 watch_int->value = -1;
648 }
649
650 GType
watch_int_get_type(void)651 watch_int_get_type( void )
652 {
653 static GType watch_int_type = 0;
654
655 if( !watch_int_type ) {
656 static const GTypeInfo info = {
657 sizeof( WatchIntClass ),
658 NULL, /* base_init */
659 NULL, /* base_finalize */
660 (GClassInitFunc) watch_int_class_init,
661 NULL, /* class_finalize */
662 NULL, /* class_data */
663 sizeof( WatchInt ),
664 32, /* n_preallocs */
665 (GInstanceInitFunc) watch_int_init,
666 };
667
668 watch_int_type = g_type_register_static( TYPE_WATCH,
669 "WatchInt", &info, 0 );
670 }
671
672 return( watch_int_type );
673 }
674
675 static Watch *
watch_int_new(Watchgroup * watchgroup,const char * name)676 watch_int_new( Watchgroup *watchgroup, const char *name )
677 {
678 WatchInt *watch_int = WATCH_INT( g_object_new( TYPE_WATCH_INT, NULL ) );
679
680 watch_link( WATCH( watch_int ), watchgroup, name );
681
682 return( WATCH( watch_int ) );
683 }
684
685 int
watch_int_get(Watchgroup * watchgroup,const char * name,int fallback)686 watch_int_get( Watchgroup *watchgroup, const char *name, int fallback )
687 {
688 Watch *watch;
689 void *value;
690
691 if( !watchgroup ||
692 !name )
693 return( fallback );
694
695 if( !(watch = watch_find( watchgroup, name )) )
696 watch = watch_int_new( watchgroup, name );
697
698 g_assert( IS_WATCH_INT( watch ) );
699
700 if( !watch_get( watch, &value ) )
701 return( fallback );
702
703 return( *((int *) value) );
704 }
705
706 static WatchClass *watch_path_parent_class = NULL;
707
708 static void
watch_path_finalize(GObject * gobject)709 watch_path_finalize( GObject *gobject )
710 {
711 WatchPath *watch_path;
712
713 g_return_if_fail( gobject != NULL );
714 g_return_if_fail( IS_WATCH_PATH( gobject ) );
715
716 #ifdef DEBUG
717 printf( "watch_path_finalize\n" );
718 #endif /*DEBUG*/
719
720 watch_path = WATCH_PATH( gobject );
721
722 /* My instance destroy stuff.
723 */
724 IM_FREEF( slist_free_all, watch_path->value );
725
726 G_OBJECT_CLASS( watch_path_parent_class )->finalize( gobject );
727 }
728
729 static gboolean
watch_path_update(Watch * watch)730 watch_path_update( Watch *watch )
731 {
732 WatchPath *watch_path = WATCH_PATH( watch );
733 PElement *root = &watch->row->expr->root;
734 GSList *value;
735
736 #ifdef DEBUG
737 printf( "watch_path_update\n" );
738 #endif /*DEBUG*/
739
740 if( !heap_get_lstring( root, &value ) )
741 return( FALSE );
742
743 IM_FREEF( slist_free_all, watch_path->value );
744 watch_path->value = value;
745
746 return( TRUE );
747 }
748
749 static void *
watch_path_get_value(Watch * watch)750 watch_path_get_value( Watch *watch )
751 {
752 WatchPath *watch_path = WATCH_PATH( watch );
753
754 return( (void *) &watch_path->value );
755 }
756
757 static void
watch_path_class_init(WatchPathClass * class)758 watch_path_class_init( WatchPathClass *class )
759 {
760 GObjectClass *gobject_class = (GObjectClass *) class;
761 WatchClass *watch_class = (WatchClass *) class;
762
763 watch_path_parent_class = g_type_class_peek_parent( class );
764
765 gobject_class->finalize = watch_path_finalize;
766
767 watch_class->update = watch_path_update;
768 watch_class->get_value = watch_path_get_value;
769 }
770
771 static void
watch_path_init(WatchPath * watch_path)772 watch_path_init( WatchPath *watch_path )
773 {
774 #ifdef DEBUG
775 printf( "watch_path_init\n" );
776 #endif /*DEBUG*/
777
778 watch_path->value = NULL;
779 }
780
781 GType
watch_path_get_type(void)782 watch_path_get_type( void )
783 {
784 static GType watch_path_type = 0;
785
786 if( !watch_path_type ) {
787 static const GTypeInfo info = {
788 sizeof( WatchPathClass ),
789 NULL, /* base_init */
790 NULL, /* base_finalize */
791 (GClassInitFunc) watch_path_class_init,
792 NULL, /* class_finalize */
793 NULL, /* class_data */
794 sizeof( WatchPath ),
795 32, /* n_preallocs */
796 (GInstanceInitFunc) watch_path_init,
797 };
798
799 watch_path_type = g_type_register_static( TYPE_WATCH,
800 "WatchPath", &info, 0 );
801 }
802
803 return( watch_path_type );
804 }
805
806 static Watch *
watch_path_new(Watchgroup * watchgroup,const char * name)807 watch_path_new( Watchgroup *watchgroup, const char *name )
808 {
809 WatchPath *watch_path = WATCH_PATH(
810 g_object_new( TYPE_WATCH_PATH, NULL ) );
811
812 watch_link( WATCH( watch_path ), watchgroup, name );
813
814 return( WATCH( watch_path ) );
815 }
816
817 GSList *
watch_path_get(Watchgroup * watchgroup,const char * name,GSList * fallback)818 watch_path_get( Watchgroup *watchgroup, const char *name, GSList *fallback )
819 {
820 Watch *watch;
821 void *value;
822
823 if( !watchgroup )
824 return( fallback );
825
826 if( !(watch = watch_find( watchgroup, name )) )
827 watch = watch_path_new( watchgroup, name );
828
829 g_assert( IS_WATCH_PATH( watch ) );
830
831 if( !watch_get( watch, &value ) )
832 return( fallback );
833
834 return( *((GSList **) value) );
835 }
836
837 static WatchClass *watch_bool_parent_class = NULL;
838
839 static gboolean
watch_bool_update(Watch * watch)840 watch_bool_update( Watch *watch )
841 {
842 WatchBool *watch_bool = WATCH_BOOL( watch );
843 PElement *root = &watch->row->expr->root;
844
845 #ifdef DEBUG
846 printf( "watch_bool_update: %s\n", NN( IOBJECT( watch )->name ) );
847 #endif /*DEBUG*/
848
849 if( PEISNOVAL( root ) )
850 return( FALSE );
851 if( !PEISBOOL( root ) ) {
852 heap_error_typecheck( root, IOBJECT( watch )->name, "bool" );
853 return( FALSE );
854 }
855
856 watch_bool->value = PEGETBOOL( root );
857
858 return( TRUE );
859 }
860
861 static void *
watch_bool_get_value(Watch * watch)862 watch_bool_get_value( Watch *watch )
863 {
864 WatchBool *watch_bool = WATCH_BOOL( watch );
865
866 return( (void *) &watch_bool->value );
867 }
868
869 static void
watch_bool_class_init(WatchBoolClass * class)870 watch_bool_class_init( WatchBoolClass *class )
871 {
872 WatchClass *watch_class = (WatchClass *) class;
873
874 watch_bool_parent_class = g_type_class_peek_parent( class );
875
876 watch_class->update = watch_bool_update;
877 watch_class->get_value = watch_bool_get_value;
878 }
879
880 static void
watch_bool_init(WatchBool * watch_bool)881 watch_bool_init( WatchBool *watch_bool )
882 {
883 #ifdef DEBUG
884 printf( "watch_bool_init\n" );
885 #endif /*DEBUG*/
886
887 watch_bool->value = FALSE;
888 }
889
890 GType
watch_bool_get_type(void)891 watch_bool_get_type( void )
892 {
893 static GType watch_bool_type = 0;
894
895 if( !watch_bool_type ) {
896 static const GTypeInfo info = {
897 sizeof( WatchBoolClass ),
898 NULL, /* base_init */
899 NULL, /* base_finalize */
900 (GClassInitFunc) watch_bool_class_init,
901 NULL, /* class_finalize */
902 NULL, /* class_data */
903 sizeof( WatchBool ),
904 32, /* n_preallocs */
905 (GInstanceInitFunc) watch_bool_init,
906 };
907
908 watch_bool_type = g_type_register_static( TYPE_WATCH,
909 "WatchBool", &info, 0 );
910 }
911
912 return( watch_bool_type );
913 }
914
915 static Watch *
watch_bool_new(Watchgroup * watchgroup,const char * name)916 watch_bool_new( Watchgroup *watchgroup, const char *name )
917 {
918 WatchBool *watch_bool = WATCH_BOOL(
919 g_object_new( TYPE_WATCH_BOOL, NULL ) );
920
921 watch_link( WATCH( watch_bool ), watchgroup, name );
922
923 return( WATCH( watch_bool ) );
924 }
925
926 gboolean
watch_bool_get(Watchgroup * watchgroup,const char * name,gboolean fallback)927 watch_bool_get( Watchgroup *watchgroup, const char *name, gboolean fallback )
928 {
929 Watch *watch;
930 void *value;
931
932 if( !watchgroup )
933 return( fallback );
934
935 if( !(watch = watch_find( watchgroup, name )) )
936 watch = watch_bool_new( watchgroup, name );
937
938 g_assert( IS_WATCH_BOOL( watch ) );
939
940 if( !watch_get( watch, &value ) )
941 return( fallback );
942
943 return( *((gboolean *) value) );
944 }
945
946 static WatchClass *watch_string_parent_class = NULL;
947
948 static void
watch_string_finalize(GObject * gobject)949 watch_string_finalize( GObject *gobject )
950 {
951 WatchString *watch_string;
952
953 g_return_if_fail( gobject != NULL );
954 g_return_if_fail( IS_WATCH_STRING( gobject ) );
955
956 #ifdef DEBUG
957 printf( "watch_string_finalize\n" );
958 #endif /*DEBUG*/
959
960 watch_string = WATCH_STRING( gobject );
961
962 /* My instance destroy stuff.
963 */
964 IM_FREE( watch_string->value );
965
966 G_OBJECT_CLASS( watch_string_parent_class )->finalize( gobject );
967 }
968
969 static gboolean
watch_string_update(Watch * watch)970 watch_string_update( Watch *watch )
971 {
972 WatchString *watch_string = WATCH_STRING( watch );
973 PElement *root = &watch->row->expr->root;
974 char value[1024];
975
976 #ifdef DEBUG
977 printf( "watch_string_update\n" );
978 #endif /*DEBUG*/
979
980 if( !heap_get_string( root, value, 1024 ) )
981 return( FALSE );
982
983 IM_SETSTR( watch_string->value, value );
984
985 return( TRUE );
986 }
987
988 static void *
watch_string_get_value(Watch * watch)989 watch_string_get_value( Watch *watch )
990 {
991 WatchString *watch_string = WATCH_STRING( watch );
992
993 return( (void *) &watch_string->value );
994 }
995
996 static void
watch_string_class_init(WatchStringClass * class)997 watch_string_class_init( WatchStringClass *class )
998 {
999 GObjectClass *gobject_class = (GObjectClass *) class;
1000 WatchClass *watch_class = (WatchClass *) class;
1001
1002 watch_string_parent_class = g_type_class_peek_parent( class );
1003
1004 gobject_class->finalize = watch_string_finalize;
1005
1006 watch_class->update = watch_string_update;
1007 watch_class->get_value = watch_string_get_value;
1008 }
1009
1010 static void
watch_string_init(WatchString * watch_string)1011 watch_string_init( WatchString *watch_string )
1012 {
1013 #ifdef DEBUG
1014 printf( "watch_string_init\n" );
1015 #endif /*DEBUG*/
1016
1017 watch_string->value = NULL;
1018 }
1019
1020 GType
watch_string_get_type(void)1021 watch_string_get_type( void )
1022 {
1023 static GType watch_string_type = 0;
1024
1025 if( !watch_string_type ) {
1026 static const GTypeInfo info = {
1027 sizeof( WatchStringClass ),
1028 NULL, /* base_init */
1029 NULL, /* base_finalize */
1030 (GClassInitFunc) watch_string_class_init,
1031 NULL, /* class_finalize */
1032 NULL, /* class_data */
1033 sizeof( WatchString ),
1034 32, /* n_preallocs */
1035 (GInstanceInitFunc) watch_string_init,
1036 };
1037
1038 watch_string_type = g_type_register_static( TYPE_WATCH,
1039 "WatchString", &info, 0 );
1040 }
1041
1042 return( watch_string_type );
1043 }
1044
1045 static Watch *
watch_string_new(Watchgroup * watchgroup,const char * name)1046 watch_string_new( Watchgroup *watchgroup, const char *name )
1047 {
1048 WatchString *watch_string = WATCH_STRING(
1049 g_object_new( TYPE_WATCH_STRING, NULL ) );
1050
1051 watch_link( WATCH( watch_string ), watchgroup, name );
1052
1053 return( WATCH( watch_string ) );
1054 }
1055
1056 const char *
watch_string_get(Watchgroup * watchgroup,const char * name,const char * fallback)1057 watch_string_get( Watchgroup *watchgroup,
1058 const char *name, const char *fallback )
1059 {
1060 Watch *watch;
1061 void *value;
1062
1063 if( !watchgroup )
1064 return( fallback );
1065
1066 if( !(watch = watch_find( watchgroup, name )) )
1067 watch = watch_string_new( watchgroup, name );
1068
1069 g_assert( IS_WATCH_STRING( watch ) );
1070
1071 if( !watch_get( watch, &value ) )
1072 return( fallback );
1073
1074 return( *((const char **) value) );
1075 }
1076
1077