aboutsummaryrefslogtreecommitdiff
path: root/extensions/xgui/bin/xgui-client.sh
blob: 120901877e826e5f1d8c367ebb2645e96d70a779 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
#!/bin/sh
# the next line restarts using wish \
exec wish "$0" "$@"


#################################################
puts "pd(x) - Step 2 : xgui-client"
puts "xgui b0.10 dh200209xx"
puts "Damien HENRY (c)"

#################################################
# define the globals variables needed for a node
global xgui_gui
global xgui_cmd_out
global data_data

global from_all

global host_name
global host_port
global xgui_me
set host_name localhost
set host_port 4877
set xgui_me "$host_name:$host_port"

global pd_name
global pd_port
global pd_sok
global xgui_pd
set pd_name xxx
set pd_port 000
set xgui_pd "$pd_name:$pd_port"
set pd_sok -1

global neibourg_list
global neibourg_data
set neibourg_list [list]
set neibourg_data [list]
set data_data [list]
set xgui_gui 1
set xgui_cmd_out 0

#################################################
# Read what are the argument
if { [lsearch argv --help] != -1 } { puts "xgui localhost 4877 -nogui -no_cmd_out" }

#################################################
# puts up my windows
if { $xgui_gui } {
  global text2out
  global text_from_outside
  global text_comment
  wm title . "Xgui b0.09"
  frame .haut
  frame .config1
  frame .config2
  frame .bas
  entry .haut.e_in -width 50 -textvariable text2in
  entry .haut.e_fo -width 50 -textvariable text_from_outside -state disabled 
  entry .haut.e_rem -width 50 -textvariable text_comment -state disabled
  entry .haut.t_out -width 50 -textvariable text2out -state disabled

  entry .config1.host -width 10 -textvariable host_name
  entry .config1.port -width 5 -textvariable host_port

  entry .config2.host -width 10 -textvariable pd_name
  entry .config2.port -width 5 -textvariable pd_port

  button .config1.do -text "change"  -command {
    global xgui_me
    global host_name
    global host_port
    global from_all
    set xgui_me "$host_name:$host_port"
    catch {close $from_all}
    set from_all [socket -server seg_receive $host_port]
  }  

  button .config2.do -text "change"  -command {
    global xgui_pd
    global pd_name
    global pd_port
    set xgui_pd "$pd_name:$pd_port"
    catch {close $pd_sok}
    catch {set pd_sok [socket $pd_name $pd_port]}
  }  

  button .bas.b_quit -text "quit" -width 7 -command {
    send2nodes / */ "# $xgui_me disconnected"
    do_this "$xgui_me/ ~/ disconnect *" xgui
    exit
  }
  button .bas.b_do -text do -width 7 -command { do_this $text2in xgui}
  button .bas.b_clear -text clear -width 7 -command { set text2in "" }

  pack .haut.e_in .haut.e_fo .haut.t_out .haut.e_rem
  pack .config1.host .config1.port  .config1.do -side left
  pack .config2.host .config2.port  .config2.do -side left
  pack .bas.b_do .bas.b_clear .bas.b_quit -side left -pady 2 -padx 5
  pack .haut .config1 .config2 .bas -pady 2
  wm resizable . false false
}

#################################################
# definition de la partie serveur

catch {set from_all [socket -server seg_receive $host_port]}

proc seg_receive {channel addr port} {
  global xgui_me
  fileevent $channel readable "readLine $channel $addr $port"
  do_this "/ */ # $xgui_me connected from $channel $addr $port" 0
}

proc readLine {channel addr port} {
  global neibourg_list
  global neibourg_data
  global xgui_me
  global text_from_outside
  if {[gets $channel line]<0} {
    fileevent $channel readable {}
    after idle "close $channel"
    set n [lsearch $neibourg_data $channel]
    if {$n != -1 } {
      set neibourg_list [lreplace $neibourg_list $n $n]
      set neibourg_data [lreplace $neibourg_data $n $n]
    }
    send2nodes / */ "# $xgui_me disconnected from $addr:$port"
  } else {
#     catch { do_this $line $channel }
    set text_from_outside "$addr:$port $line"
#     set text_from_outside "$line"
    do_this $line $channel
  }
}


#################################################
# tell that every thing OK
set text_comment "$xgui_me created" 

# end of the initialisations
########################################################################################

#################################################
#methods for xgui_node
proc xgui_node_add_canvas {canvas_name} {
  set canvas_name [string trim $canvas_name "/"]
  set canvas_name [split $canvas_name "/"]
  set canvas_name [lindex $canvas_name end]
  destroy .$canvas_name
  data_forget ~/$canvas_name
  toplevel .$canvas_name
  wm title .$canvas_name $canvas_name
  wm resizable .$canvas_name false false
  canvas .$canvas_name.$canvas_name
  pack .$canvas_name.$canvas_name
  data_remember ~/$canvas_name/ "~/$canvas_name add_canvas"
  send2nodes / */ "# added ~/$canvas_name"

  set c .$canvas_name.$canvas_name
  $c bind all <Any-Enter> "itemEnter $c"
  $c bind all <Any-Leave> "itemLeave $c"
  bind $c <1> "itemStartDrag $c %x %y click"
  bind $c <2> "itemStartDrag $c %x %y m-click"
  bind $c <3> "itemStartDrag $c %x %y r_click"
  bind $c <Shift-1> "itemStartDrag $c %x %y s-click"
  bind $c <Shift-2> "itemStartDrag $c %x %y s-m-click"
  bind $c <Shift-3> "itemStartDrag $c %x %y s-r-click"
  bind $c <Control-1> "itemStartDrag $c %x %y c-click"
  bind $c <Control-2> "itemStartDrag $c %x %y c-m-click"
  bind $c <Control-3> "itemStartDrag $c %x %y c-r-click"
  bind $c <B1-Motion> "itemDrag $c %x %y drag"
  bind $c <B2-Motion> "itemDrag $c %x %y m-drag"
  bind $c <B3-Motion> "itemDrag $c %x %y r-drag"
  bind $c <Shift-B1-Motion> "itemDrag $c %x %y s-drag"
  bind $c <Shift-B2-Motion> "itemDrag $c %x %y s-m-drag"
  bind $c <Shift-B3-Motion> "itemDrag $c %x %y s-r-drag"
  bind $c <Key> "itemKeyPress $c %A %k"
}

proc xgui_node_del_canvas {canvas_name } {
  global text_comment
  set canvas_name [string trim $canvas_name "/"]
  set canvas_name [split $canvas_name "/"]
  set canvas_name [lindex $canvas_name end]
  destroy .$canvas_name
  data_forget ~/$canvas_name
  set text_comment "deleted $canvas_name"
}

proc xgui_node_error {from error} {
  global text_comment
  set text_comment "# error : unable to do <$error> ($from)"
}

proc xgui_node_connect { c_who c_from channel } {
  global neibourg_list
  global neibourg_data
  global xgui_me
  global text_comment
  set c_from [string trim $c_from "/"]
  switch $c_who {
    "me"  {
      set n [lsearch $neibourg_data $channel]
      if { $n == -1 } {
        lappend neibourg_list  $c_from
        lappend neibourg_data  $channel
        set text_comment "$xgui_me connect himself to $c_from onto channel $channel"
      } else {
        set text_comment "$xgui_me already connected to $c_from onto channel $channel"
      }
    }
    "pd" {
      global pd_name
      global pd_port
      global pd_sok
      global xgui_pd
      set c_host [split $c_from ":"]
      set pd_name [lindex $c_host 0]
      set pd_port [lindex $c_host 1]
      set xgui_pd "$pd_name:$pd_port"
      set pd_sok [socket -async $pd_name $pd_port]
 #     set pd_sok [socket $pd_name $pd_port]
      if { $pd_sok != -1 } {
        set text_comment " $xgui_me connected to pd"
      } else { set text_comment "connection refused with pd" }
    }
    default  {
      set c_host [split $c_who ":"]
      set c_name [lindex $c_host 0]
      set c_port [lindex $c_host 1]
      set sok -1
      catch {set sok [socket -async $c_name $c_port]}
      if { $sok != -1 } {
        lappend neibourg_list  $c_who
        lappend neibourg_data  $sok
	fileevent $sok readable [list read_and_do $sok]
        set text_comment "$xgui_me connected $c_who"
      } else { set text_comment "connection refused with $c_who" }
    }
  }
}

proc xgui_node_disconnect { d_who d_from channel} {
  global neibourg_list
  global neibourg_data
  global text_comment
  switch $d_who {
    "me" {
      set d_who [string trim $d_from "/"]
      set n [lsearch $neibourg_list $d_who]
      if {$n != -1 } {
        catch { close [lrange $neibourg_data $n $n] }
        set neibourg_list [lreplace $neibourg_list $n $n]
        set neibourg_data [lreplace $neibourg_data $n $n]
        set text_comment "$d_who disconnected himself"
      } else { set text_comment "error $d_from not a neibourg" }
    }

    "pd" {
      global pd_name
      global pd_port
      global pd_sok
      global xgui_pd
      set pd_name none
      set pd_port none
      set xgui_pd "$pd_name:$pd_port"
      set pd_sok -1
      catch {close pd_sok}
    }
    "*" {
      foreach sok $neibourg_data { close $sok }
      set neibourg_list [list]
      set neibourg_data [list]
      set text_comment "$d_from disconnect *"
    }
    default {
      set n [lsearch $neibourg_list $d_who]
      if {$n != -1 } {
        catch { close [lrange $neibourg_data $n $n]
 }
        set neibourg_list [lreplace $neibourg_list $n $n]
        set neibourg_data [lreplace $neibourg_data $n $n]
        set text_comment "$d_who disconnected $d_from"
      } else { set text_comment "error $d_who not a neibourg" }
    }
  }
}

proc xgui_node_hide { canvas } {
  set canvas_name [string trim $canvas_name "/"]
  set canvas_name [split $canvas_name "/"]
  set canvas_name [lindex $canvas_name end]
  destroy .$canvas_name
}

proc xgui_node_neibourg { w_from } {
  global neibourg_list
  global neibourg_data
  global xgui_me
  foreach name $neibourg_list {
    send2nodes / $w_from "# $xgui_me connected to $name"
  }
}

proc xgui_node_clone { obj new_obj } {
  data_clone $obj $new_obj
}

proc xgui_node_load { file } {
  data_load $file
}

proc xgui_node_save { obj file } {
  data_save $obj $file
}

proc xgui_node_load_coord { file } {
  data_load_send $file
}

proc xgui_node_save_coord { obj file } {
  data_save_param $obj coord $file
}

proc xgui_node_debug { from var } {
  global host_name
  global host_port
  global xgui_me
  global neibourg_list
  global neibourg_data
  global xgui_gui
  global xgui_cmd_out
  global data_data
  global text_comment
  global pd_name
  global pd_port
  global pd_sok
  global xgui_pd
  global from_all
  set text_comment "$var = [subst $var ]" 
}

proc xgui_node_help { w_from } {
  send2nodes / $w_from "# method: connect who"
  send2nodes / $w_from "# method: disconnect who"
  send2nodes / $w_from "# method: neibourg"  
  send2nodes / $w_from "# method: ping"  
  send2nodes / $w_from "# method: add_canvas" 
  send2nodes / $w_from "# method: del_canvas"        
}
#################################################
#methods for canvas

proc canvas_size {canvas_name x y} {
  .$canvas_name.$canvas_name configure -width $x
  .$canvas_name.$canvas_name configure -height $y
  wm geometry .$canvas_name
  data_remember ~/$canvas_name//size "~/$canvas_name  size $x $y"
}

proc canvas_color {canvas_name color} {
 .$canvas_name.$canvas_name configure -bg $color
  data_remember ~/$canvas_name//color "~/$canvas_name color $color"
 }

#################################################
#methods for all objects

proc obj_move {canvas gobj_name x y } {
  global xgui_pd
  catch {.$canvas.$canvas move $gobj_name $x $y
    send2pd / pd/$canvas/$gobj_name "coord [.$canvas.$canvas coords $gobj_name]"
    data_remember ~/$canvas/$gobj_name//coord "~/$canvas/$gobj_name coord [.$canvas.$canvas coords $gobj_name]"
  }
}

proc obj_color {canvas gobj_name new_color} {
  .$canvas.$canvas itemconfigure $gobj_name -fill $new_color
  data_remember ~/$canvas/$gobj_name//color  "~/$canvas/$gobj_name color $new_color"
}

proc obj_border {canvas gobj_name new_color} {
  .$canvas.$canvas itemconfigure $gobj_name -outline $new_color
  data_remember ~/$canvas/$gobj_name//border "~/$canvas/$gobj_name border $new_color"
}

proc obj_raise {canvas gobj_name } {
  .$canvas.$canvas raise $gobj_name
  data_remember ~/$canvas/$gobj_name//raise "~/$canvas/$gobj_name raise" 
}

proc obj_coord {canvas gobj_name x1 y1 x2 y2 } {
  catch {
    .$canvas.$canvas coords $gobj_name $x1 $y1 $x2 $y2
    data_remember ~/$canvas/$gobj_name//coord "~/$canvas/$gobj_name coord $x1 $y1 $x2 $y2" 
  }
}

proc obj_xy1 {canvas gobj_name x1 y1 } {
  catch {
    set old_coord [.$canvas.$canvas coords $gobj_name]
    .$canvas.$canvas coords $gobj_name $x1 $y1 [lindex $old_coord 2] [lindex $old_coord 3]
    data_remember ~/$canvas/$gobj_name//coord "~/$canvas/$gobj_name coord $x1 $y1 [lindex $old_coord 2] [lindex $old_coord 3]"
  }
}

proc obj_xy2 {canvas gobj_name x2 y2 } {
  catch {
    set old_coord [.$canvas.$canvas coords $gobj_name]
    .$canvas.$canvas coords $gobj_name [lindex $old_coord 0] [lindex $old_coord 1] $x2 $y2
    data_remember ~/$canvas/$gobj_name//coord "~/$canvas/$gobj_name coord [lindex $old_coord 0] [lindex $old_coord 1] $x2 $y2"
  }
}

proc obj_width {canvas gobj_name new_width} {
  .$canvas.$canvas itemconfigure $gobj_name -width $new_width
  data_remember ~/$canvas/$gobj_name//width "~/$canvas/$gobj_name width $new_width"
}

proc obj_near {canvas gobj_name x y} {
  # to be done...
}

proc obj_del {canvas obj_name} {
  .$canvas.$canvas delete $obj_name
  send2nodes /$canvas */$canvas "# deleted $obj_name"
  data_forget ~/$canvas/$obj_name
}

#################################################
#methods for seg

proc seg_add {canvas gobj_name x1 y1 x2 y2 } {
  .$canvas.$canvas delete $gobj_name
  data_forget ~/$canvas/$gobj_name
  .$canvas.$canvas create line $x1 $y1 $x2 $y2 -width 3 -tags $gobj_name -capstyle round
  # send2nodes /$canvas */$canvas "added $gobj_name"
  data_remember ~/$canvas/$gobj_name/ "~/$canvas/$gobj_name add_seg"
}

proc seg_caps {canvas gobj_name new_cap} {
  .$canvas.$canvas itemconfigure $gobj_name -capstyle $new_cap
  data_remember ~/$canvas/$gobj_name//caps "~/$canvas/$gobj_name caps $new_cap"
}

#################################################
#methods for text

proc text_add {canvas gobj_name x1 y1 text } {
  .$canvas.$canvas delete $gobj_name
  data_forget ~/$canvas/$gobj_name
  .$canvas.$canvas create text $x1 $y1 -text $text -tags $gobj_name -anchor sw
  # send2nodes /$canvas */$canvas "added $gobj_name"
  data_remember ~/$canvas/$gobj_name/ "~/$canvas/$gobj_name add_text"
}

proc text_value {canvas gobj_name value} {
  .$canvas.$canvas itemconfigure $gobj_name -text $value
  data_remember ~/$canvas/$gobj_name//text "~/$canvas/$gobj_name text $value"
}

proc text_anchor {canvas gobj_name value} {
  .$canvas.$canvas itemconfigure $gobj_name -anchor $value
  data_remember ~/$canvas/$gobj_name//anchor "~/$canvas/$gobj_name anchor $value"
}

proc text_justify {canvas gobj_name value} {
  .$canvas.$canvas itemconfigure $gobj_name -justify $value
  data_remember ~/$canvas/$gobj_name//justify "~/$canvas/$gobj_name justify $value"
}

proc text_pos {canvas gobj_name x y} {
 .$canvas.$canvas coords $gobj_name $x $y
  data_remember ~/$canvas/$gobj_name//pos "~/$canvas/$gobj_name pos $x $y"
}

#################################################
#methods for rect

proc rect_add {canvas gobj_name x1 y1 x2 y2 } {
  .$canvas.$canvas delete $gobj_name
  data_forget ~/$canvas/$gobj_name
  .$canvas.$canvas create rectangle $x1 $y1 $x2 $y2 -width 2 -tags $gobj_name
  # send2nodes /$canvas */$canvas "# added $gobj_name"
  data_remember ~/$canvas/$gobj_name/ "~/$canvas/$gobj_name add_rect"
}

#################################################
#methods for arc

proc arc_add {canvas gobj_name x1 y1 x2 y2  start width} {
  .$canvas.$canvas delete $gobj_name
  data_forget ~/$canvas/$gobj_name
  .$canvas.$canvas create arc $x1 $y1 $x2 $y2 -start $start -extent $width -width 2 -tags $gobj_name
  # send2nodes /$canvas */$canvas "# added $gobj_name "
  data_remember ~/$canvas/$gobj_name/ "~/$canvas/$gobj_name add_arc"
}

proc arc_start {canvas gobj_name new_start} {
  .$canvas.$canvas itemconfigure $gobj_name -start $new_start
  data_remember ~/$canvas/$gobj_name//start "~/$canvas/$gobj_name start $new_start"}

proc arc_width {canvas gobj_name new_width} {
  .$canvas.$canvas itemconfigure $gobj_name -extent $new_width
  data_remember ~/$canvas/$gobj_name//angle "~/$canvas/$gobj_name angle $new_width"}

proc arc_style {canvas gobj_name new_style} {
  .$canvas.$canvas itemconfigure $gobj_name -style $new_style
  data_remember ~/$canvas/$gobj_name//style "~/$canvas/$gobj_name style $new_style "}

################################################
# Set up event bindings for all canvas:

proc itemStartDrag {c x y event} {
    global xgui_pd
    global lastX lastY
    global my_selected
    set lastX [$c canvasx $x]
    set lastY [$c canvasy $y]
    set my_selected [lindex [$c gettags current] 0]
    set c [lindex [split $c "."] 1]
    send2pd / pd/$c/$my_selected "$event $x $y"
}

proc itemDrag {c x y event} {
    global xgui_pd
    global lastX lastY
    global my_selected
    set x [$c canvasx $x]
    set y [$c canvasy $y]
    set c [lindex [split $c "."] 1]
    send2pd / pd/$c/$my_selected "$event [expr $x-$lastX] [expr $y-$lastY]"
    set lastX $x
    set lastY $y
}

proc itemEnter {c} {
  global xgui_pd
  set my_item [lindex [$c gettags current] 0]
  set c [lindex [split $c "."] 1]
  send2pd / pd/$c/$my_item enter
}

proc itemLeave {c} {
  global xgui_pd
  set my_item [lindex [$c gettags current] 0]
  set c [lindex [split $c "."] 1]
  send2pd / pd/$c/$my_item leave
}

proc itemKeyPress {c ascii num} {
  global xgui_pd
  set my_item [lindex [$c gettags current] 0]
  set c [lindex [split $c "."] 1]
  send2pd / pd/$c/$my_item "keypress $ascii $num"
  send2pd / pd/$c "keypress $ascii $num"
}

#####################################################################################
# Here the procedures that keep a memory about all objectz.

proc data_remember {obj_sel m} {
  global data_data
  set line_to_destroy 0
  foreach line $data_data  {
    if {[string match "$obj_sel/*"  $line] == 1} {
      set line_to_destroy $line
    }
  }
  if { $line_to_destroy !=0 } {
    set n [lsearch $data_data $line_to_destroy ]
    set data_data [lreplace $data_data $n $n "$obj_sel/ $m" ]
  } else {
    lappend data_data "$obj_sel/ $m"
  }
}

proc data_forget { obj } {
  global data_data
  while { [lsearch $data_data $obj/* ] != -1} {
    set n [lsearch $data_data $obj/* ]
    set data_data [lreplace $data_data $n $n]
  }
}

proc data_clone { from_obj to_new_obj } {
  global data_data 
  foreach line $data_data  {
    if {[string match "$from_obj/*"  $line] == 1} {
      set new_line [join [lreplace [split $line] 0 0 ] ] 
      regsub -all -- $from_obj $new_line $to_new_obj newest_line
      do_this "~/ $newest_line" 0 
    }
  }
} 

proc data_save { from_obj file } {
  global data_data 
  set file_chn [open $file w]
  foreach line $data_data  {
    if {[string match "$from_obj/*"  $line] == 1} {
      set new_line [join [lreplace [split $line] 0 0 ] ] 
      puts $file_chn "$new_line"
    }
  }
  close $file_chn
}

proc data_save_param { from_obj selector file } {
  global data_data 
  set file_chn [open $file w]
  foreach line $data_data  {
    if {[string match "$from_obj/*//$selector*"  $line] == 1} {
      set new_line [join [lreplace [split $line] 0 0 ] ] 
      puts $file_chn "$new_line"
    }
  }
  close $file_chn
}

proc data_load { file } {
  global data_data
  set file_chn [open $file r]
  while {[eof $file_chn]==0} {
    set line [gets $file_chn]
    do_this "~/ $line" 0    
  } 
  close $file_chn
}

proc data_load_send { file } {
  global data_data
  set file_chn [open $file r]
  while {[eof $file_chn]==0} {
    set line [gets $file_chn]
    set line2s [split $line]
    set line2s [join [linsert $line2s 1 update]]
#    regsub -all -- ~/ $line2s */ new_line
#    do_this "~/ $line" 0
    send2pd / $line2s ""
  } 
  close $file_chn
}


################################################################################################
#anything to send somewhere ???
proc send2nodes { m_from m_to ms2send } {
  global xgui_gui
  global xgui_cmd_out
  global text2out
  global xgui_me
  global neibourg_list
  global neibourg_data

  global text_comment

  set m2send "$xgui_me$m_from $m_to $ms2send"
  set m_to [string trim $m_to "/"]
  set m_to_l [split $m_to "/"]
  set m_to_node [lindex $m_to_l 0]

  if { $xgui_gui == 1 } {
    set text2out $m2send
  }
  if { $xgui_cmd_out == 1 } {
    puts $m2send
  }

  switch [lindex [split $m_to "/"] 0 ] {
    "*" {
      foreach n $neibourg_list {
        regsub -all -- {\*} $m_to $n m2
        send2nodes $m_from $m2 $ms2send
      }
    }
    "." {
      foreach n $neibourg_data {
        catch {puts $n $ms2send;flush $n}
      }
    }
    default {
      set n [lsearch $neibourg_list $m_to_node]
      if { $n != -1 } {
      # if catch = error then we have to remove the link.
        catch {
          puts [lrange $neibourg_data $n $n] "$m2send;"
          flush [lrange $neibourg_data $n $n]
        }
      } else {
        set $text_comment "didn't find any coresponding neigbourg"
      }
    }
  }
}

proc send2pd { m_from m_to ms2send } {
  global xgui_gui
  global xgui_cmd_out
  global text2out
  global xgui_me
  global pd_sok

  set m2send "$xgui_me$m_from $m_to $ms2send;"

  if { $xgui_gui == 1 } {
    set text2out $m2send
  }
  if { $xgui_cmd_out == 1 } {
    puts $m2send
  }

 #  catch {
    puts $pd_sok $m2send ; flush $pd_sok
 # }
}


#####################################################################################
# the 3 main proc that do every thing      ##########################################
#####################################################################################

proc read_and_do { channel } {
  gets $channel message
  global text_from_outside
  set text_from_outside "$channel \"$message"
  do_this $message $channel
}

proc do_this { m channel} {
  global xgui_me
  set m [string trim $m ";"]
  if {[llength $m] >= 3} {
    set m_to [string trim [lindex $m 1] "/"]
    set m_to_l [split $m_to "/"]
    set m_to_node [lindex $m_to_l 0]
    set m_from [string trim [lindex $m 0] "/"]
    set m_cmd [lrange $m 2 end]
    #you have to know who you are :
    if { "$m_to_node" == "$xgui_me" } { set m_to_node "~" }
    switch $m_to_node {
      "~"    { catch  {do_this_here $m_from $m_to $m_cmd $channel}
 }
      "*"    {
        # you too are a part of the whole !!!
        catch { do_this_here $m_from $m_to $m_cmd $channel
 }
        send2nodes / $m_to "[lrange $m 2 end]"
      }
      "pd"    {send2pd / $m_to "[lrange $m 2 end]"}
      default {send2nodes / $m_to "[lrange $m 2 end]"}
    }
  } else {
    if {$m == "help"} {
 #     send2nodes / $m_to "# syntax : sender receiver method args..."
    } else {
      xgui_node_error "not enought args" $m
    }
  }    
}

proc do_this_here { m_from m_to m_cmd channel} {
  global xgui_me
  global xgui_pd
  set m_to [split $m_to "/"]
  set m_from_l [split $m_from "/"]
  set m_from_node [lindex $m_from_l 0]    
  set m_selector [lindex $m_cmd 0]
  set m_argc [llength $m_cmd]-1
  if {$m_argc >= 1} { set m_argv [lrange $m_cmd 1 end]
    set a1 [lindex $m_argv 0]
    if {$m_argc >=2 } { set a2 [lindex $m_argv 1]
      if {$m_argc >=3 } { set a3 [lindex $m_argv 2]
        if {$m_argc >=4 } { set a4 [lindex $m_argv 3]
          if {$m_argc >=5 } { set a5 [lindex $m_argv 4]
            if {$m_argc >=6 } { set a6 [lindex $m_argv 5]
              if {$m_argc >=7 } { set a7 [lindex $m_argv 6]
                if {$m_argc >=8 } { set a8 [lindex $m_argv 7]
                  if {$m_argc >=9 } { set a9 [lindex $m_argv 8]
                    if {$m_argc >=10 } { set a10 [lindex $m_argv 9]
    } } } } } } } } }
  } else {set m_argv "{}" }

  switch [llength $m_to] {
   1 { # this is for the node          ##########################
     switch $m_selector {
       "add_canvas" { xgui_node_add_canvas $a1}
       "del_canvas" { xgui_node_del_canvas $a1}
       "show"       { xgui_node_clone $a1 $a1 }
       "hide"       { xgui_node_hide }
       "connect"    { if {$a1 == "pd"} { xgui_node_connect pd $a2 $channel
                       } else { xgui_node_connect $a1 $m_from $channel} }
       "connect_on" { xgui_node_connect $a1 $m_from $channel
                      send2nodes / $a1/ "connect me"
		      send2nodes / $a1/ "clone ~/$a2 $xgui_me/$a2"
		      send2nodes / $a1/ "connect_on_pd $xgui_me"  }
       "connect_on_pd" { send2nodes / $a1/ "connect pd $xgui_pd" }
       "disconnect" { xgui_node_disconnect $a1 $m_from $channel}

       "neibourg"   { xgui_node_neibourg $m_from }
       "clone"      { xgui_node_clone $a1 $a2 }
       "save"       { xgui_node_save $a1 $a2 }
       "save_coord" { xgui_node_save_coord $a1 $a2 }
       "load_coord" { xgui_node_load_coord $a1 }
       "load"       { xgui_node_load $a1 }
       "help"       { xgui_node_help $m_from }
       "debug"      { xgui_node_debug $m_from $$a1 }
       "ping"       { send2nodes / $m_from "# $m_from pinged" }
       "#"          { global text_comment ; set text_comment $m_argv}
       default    { xgui_node_error "node method $m_selector does not exist" $m_cmd }
     }
   }
   2 {  # this is for the canvas $m_c  ##########################
     set m_c [lindex $m_to 1]
     switch $m_selector {
       "add_canvas" { catch {xgui_node_add_canvas $m_c }}
       "del_canvas" { xgui_node_del_canvas $m_c }
       "size"     {canvas_size $m_c $a1 $a2}
       "color"    {canvas_color $m_c $a1}
       "del"      {obj_del $m_c $a1}
       "kill"     {obj_del $m_c $a1}
       "add_seg"  {seg_add $m_c $a1 10 10 20 20 }
       "add_text" {text_add $m_c $a1 10 10 "text"  }
       "add_rect" {rect_add $m_c $a1 10 10 20 20 }
       "add_arc"  {arc_add $m_c $a1 10 10 20 20 0 90 }
       default {xgui_node_error "canvas method $m_selector does not exist" $m_cmd }
     }
   }
   3 { # this is for the object $m_o witch is into $m_c ########
     set m_c [lindex $m_to 1]
     set m_o [lindex $m_to 2]
     switch $m_selector {
       "add_seg"  {seg_add $m_c $m_o 10 10 20 20 }
       "add_text" {text_add $m_c $m_o 10 10 "text"  }
       "add_rect" {rect_add $m_c $m_o 10 10 20 20 }
       "add_arc"  {arc_add $m_c $m_o 10 10 20 20 0 90 }
       "del"      {obj_del $m_c $m_o}
       "kill"     {obj_del $m_c $m_o}
       "show"  {obj_show  $m_c $m_o }
       "hide"  {obj_hide  $m_c $m_o }
       "move"  {obj_move  $m_c $m_o $a1 $a2}
       "scale" {obj_scale $m_c $m_o $a1 $a2 $a3 $a4 }
       "raise" {obj_raise $m_c $m_o }
       "near"  {obj_near  $m_c $m_o $a1 $a2 }
       "color" {obj_color $m_c $m_o $a1}
       "width" {obj_width $m_c $m_o $a1}
       "coord" {obj_coord $m_c $m_o $a1 $a2 $a3 $a4 }
       "xy1"   {obj_xy1   $m_c $m_o $a1 $a2 }
       "xy2"   {obj_xy2   $m_c $m_o $a1 $a2 }
       "border" {obj_border $m_c $m_o $a1}

       "caps"  {seg_caps  $m_c $m_o $a1}

       "text" {text_value $m_c $m_o $a1}
       "pos"  {text_pos $m_c $m_o $a1 $a2 }
       "anchor"  {text_anchor $m_c $m_o $a1}
       "justify" {text_justify $m_c $m_o $a1}

       "start" {arc_start $m_c $m_o $a1 }
       "angle" { arc_width $m_c $m_o $a1 }
       "style" {arc_style $m_c $m_o $a1}

       default {xgui_node_error "obj_method $m_selector does not exist" $m_argv }
     } 
   }
 }
}