@ @@"88 't XIS S hqG uy(70@pl8  92453-07A09.74.082yј 92453-07A08.56.05*v 82$Header: crt0.s,v 70.8 92/05/19 15:52:46 ssa Exp $@ `H X"0hhLX xtX X >X ^ @> @X  2``X  Pp0pX  0P PX  X   X! X!((X!88X!TfTX!HweHwX 8__X H\ < X IgGX XgG8>(p@`>(p@L>( p@`>(p@,>(tyh@yhx>(T@T>(X@X>(X@X>(&Xp@Xp >('@>(( @>(P@>(R@qh>H>IY 07? p@>l8@ $PRIVATE$$DLT$$PLT$ $SHLIB_DATA$$TEXT$ $SHLIB_INFO$ $DATA_START$ $MILLICODE$$LIT$ $LITSTATIC$$CODE$$UNWIND_START$$UNWIND$MILLICODE$$UNWIND$ $UNWIND_END$$RECOVER_START$$RECOVER$MILLICODE$ $RECOVER$ $RECOVER_END$ $PFA_COUNTER$$PFA_COUNTER_END$$DATA$ $STATICDATA$ $SHORTDATA$$SHORTSTATICDATA$$GLOBAL$ $SHORTBSS$$BSS$ $GDB_DEBUG$ $GDB_SYMBOLS$ $GDB_STRINGS$00$ 08@0@0  0@U  L 0  0  0 $ 0 40 H<0 XG0 lG0 @0 @0 @0@0@0@ \@ p@ @\ @ @ @ @X   @d@` @8 Q(  P8  D  AP ' \ s h P x           30@4 T `@ t@ @ @ @ @0 @P @p @ @ @` @ $@ 4@ D@< X@T l@l @ @ @ @0$ h  h    h T@ 8@0P@x0`@pUp U| U  @dU U 0@0UD LU@ 0U h0A 0   0 h  Up 4U$ PU0H U<P l0H UX Uh Ut8 0@ U Ux U 0   0@ 0P   0Q(   (   4@ D@ TUT (0` 0 L  0A t  (U `0 U |U D0A T  0P, @  @  0X   @ l@  0t 0|      T0 @ @Up @  @U0 ,@0 @@ 0 L@ h0 `@U @$UD 0@0 l@ 0 x@(0 @(Ut8 @0 @0 @0 @0 @ 0 @ UTU|U  LU  h @U ,0 @U0 @0 $@0 @ ,UU X U d( l0 p  @UX0U լUpU0A 0U ¬0 Ѐ0U ŔU0 $0  \0  @0U ( U0U \ <U l UU x( 0U U$U  U p U 0X U < U L0 U x0 0 0 U l0@   U P D  8U x HU ( 0  U 4X U X` 0 d `U0HU  ,U HUhU<P0A U$H 04 0H 0\@  00 l$ x                , 8 D P| \t hl  8 td  800X0`0#T00L000 0d0$00T0<,0HL0Tр0`0l0x00X00@( 0 T @  8@ @t @p @0UUp  @ @t @dU|U UX0L UD 0` 0t 0 0 dUpU$0U XU0 U 0 0 0 0 04 4ULh hU\ UlP U<P  U|h 0A U lUh0 UTUU p  U x00A    Tx  0      TUU0H @֧ @ @w @ @U lUt8UUpUT0U4 #0L !0 h $0U\ !00Ut 0 p  p0U '  /0U (0U "0U )UU8 T0U #4UD 0U "0U * 0U( +0U8 , 0UH ,x0Ut ,0U -0U -l0U -0U .p0U0 .0D /D0UX /x  p T p@ר0A 7 @D @H @L @׬UpU 0UD U  @@ @< @80A \ 0XU l     ( 0 @Ut8 L  ; h t x  0XU0 040 8   0X T(0`@0l@|0|@ @d0@U QP GUt8U|UU0HU lU U U xUhUD   IUpU x(U<PU pU < U <<UTUpU   p  p0$  p  p0P  p  p0  p  p0x`  p  p0hM  p  p0P`  p  p0\  p  p00  p  p0  T H` @$P @$x  TUUD   U  x H`U pU| (  4 0 @ 0U  PL   H   T J  @&( @\ @ِ0U H @( @ @&, @& @%$ (  4@$ D@%| X@%d h@$ x@% @$ @%UU$ U@8 T0QT   U U  \U0T 0U   0@ 80A $   T KU| @ @&0UD U0$ ,0Q< (0QP x0d |0| 00 0Q 0 0Q ,0U T0U T  ( T M @80#@&8 @00$ @&< @@ @& @D ,@H @< @4U @&@U 8@&P H@&l0$ @&L0$`@&H0$@&D @' U T UD  U p  Q U$p 8U t &Ut8U%  $ D   %,  U l ! x !  ! X !$  !0 @ !< 4 !H t !T % !` U%\  !l  !x 4 ! p ! M ! M ! M ! M ! M !@' ! O , N` ! O ! O ! O " O   Nh " O "  O ", Ot "8 Ol  Nl "D OD "P O< "\ O$ "h O  "t N  Nx  N  N  N  N Q"   N  NU&8 $U&p @  N  NU|  N  N " `  N x N " &P 8 NXU' d0Q'  D NPU(tH U(X  P NL " 8U)H @U)  \ ND " lU*  h N< " 0U*| T t N0 " P l N( " `U* x " U*  " N  " @U*  # U+$H  # N # (U+T  #, (U+x  #8 $ #D N #P dU+X   #\ N #h U+ < #t M # U, XU,$  # $U,P tU,d  # M # d0 $(U,p  # "0A, !l0Q, "l0@- 0U- 0@-8 0-T $h0-h |0@- @0@- 0@- 0@- 0 % 0@- @0P. L0@., 0T.H d0.` !0P.t 0P. 0P. 0.   # ,0. , # !0. 0U. 0U/ 0Q/$ @0/<  # $t0 %h0/T   N   /h@(x /|@(pU/0 )U/ )U d( @/ * / + @/ +U0 *,U0H *dU0p *H / +0 +  * T RU 0@P 0@ڄ 0@* 0@( 0@+0U @(U2P ,U U0 :@U UD  0 1\02 Pd 1 3 1 4 1 1l Q1, @d Q1< A @1P :( 1d 802 PL #t R # R ! R ! TD ! T< ! T0 ! T  ! T ! T  ! T ! S " S " S "  S ", S "8 S "D S "P S "\ S "h S "t S 1p S 1| S 1 S 1 St 1 Sh 1 S\  S   S  S D R  S 8 R , R  S$   R  S  S 1 0U3  -U34 - 1 1,U3H -l  S(  S0  S4  S8  S<U3`x -P 1 3 P R \ R 1 4U Ut8 h R t RU48 -$ A1 @ l RU4L` - " R x SL # R 1 8  SD #D R #\ R P2 9t T2 D0T4` 580U4t /0@)0 4p0'\ - 2, M0A4 M0P4 10) /  ST0U4 10U4 0d  - T X  4 XU|UD  4 X 4 RXUUU l0A5 R` 5 S U5 RD U54 Q U5L QU0A6X X 5d U 5p V 5| V0U6h S< 1 WPUt8 5 W 5 S 5 X$ 5 XP 5 Xp0U'$ U  Q T YH # U|UUT 6@+UD  Q6 T 6  @6 h\ 6 h  U6 hLUU 6  6 ^ 7  @7 h 7( a 74 ^ 7@ y 4 ` 7L {P 7X { 7d } 7p @Ut8 7|  7 0 7 f 7 gU9 [l 7  7  / ]t 7 ] 7 U:, [U:D [U x(U%\U/ 7 U:X` [  7 U:p8 [ 7 h 8 n 8 o< 8 o 8$ p 80 p` 8< p 8H s 8T t 8` t 8l u 8x up 8 u 8 vl 8 v 8 w4 8 w 8 x( 8 x 8 y 8 y0U&` b0U& c0U% d0U'8 _0U% e0U'L \0U' bd0U' h0( a0@:| ^0U'x [0U( i0U$   [ :@+ T b :@+ :@+ :@ڸ :@+ :@ڼU ;  ;  ;(@+U ;8  ;D  ;P  A;\ p ;p 4U;`  5p HU;P  5|  1 TU;  ;| 0( 0@00 0< 0Q< 0@< 0@< X0@= 0T9t 0T90 0=0 0$    T c8 =@@,xU  @=P | =d   \U| =p  =| @0< U = | = U> xU>,  = @ = UD U0pU>\  = $U>p U = 0A@, > 0Q?  > U@@  A>  > @ A? X ? U@  5d U@, 4 ?( U@@X lUD  ?4 | ?@  1  1  1 U U?L H 4 x0A@T 0> t ?d U9 ?p  ?| U @  T? 8 ? 0U& 0@@l T0@ 40A;  @? 0T> p @? 0) |   T g @ ʨU| @@UT @  @ DU xU @ U @,U @ HUD  @@, ?p  UA  @A L A0  A<  AH  A\ ܈ Ah t At  !<  #,  A \ !H  #P  A  A D A ݨ A ތ A ˀ A X A X @A  B  B Ӥ @B  B( ( B4 p B@  BL < TBX < Bh ȴ @B   g0U&  @B  TB    T n` CL@, C\@ Ch@, Ct@, C@, C@U| C@, C@,UU AC  C UD  7(  AC  UD <U%\ UD U0QD tU&8 @ U l AD, UD  DD X @DX  @Dh 0U&0  D| |0( 80, 0Tt    T pxU| E tUT E@( E(  E8@, EH  >  ET  @, E`@, Et h E TUUD  @E d E | UA  E L E L E P @E 0 ?p D 1  @E  F   F   AF ` AF,  F<  # , FH PUU 8 qX FT  , q` UF`  =|  Fp  F|  ,   qh  qp F  F  BL 0U&   px   T v( F@۔ F@`U|U F ' @, @F , !x , G hU " + G@, 5 lUD  UG$ !U @G8 + GP  > !l G`  Gp '( G| ', 1 \ G  1 X G H G !h @G -| @G -$ G   G , " 5  G 'l H ,X H +d !l + H x0U&   v(   T z  H( =0:@-UU|UD  UH4 @lU HL C@ H` 6Ut8UUH0 .t E C  Hl 4 " 8 QHx @H  /h H CU 0UI A  /h !< 6T C #, 6 B 7 A 8H H B 4 4l !H 8 #P 9 A 9 H : !` : #h ; H <  H = !l =  # =@ H =` H =0UI 2t0) =0@I0 10T6 0h0U% 40@IH ?0P60 /0T5 .06H >  . T | I`@- Ip@- 0K @-UUD  I@-UUt8 I `UTU%\U UI KXU X QI E AI WUDUK  D G JX 4 OT > N`U/ 1 KD I a !H _L I L0UK4 OU| AI `\ J WUKD D AJ GX J PL @J, X AJ@ b JX \U&8 Jd MUK E<UK D = LUK( E Jx K< J N< J S`U>p J OTU> 5 JPU  H` WT TJ _0A' M` J J0A9 V< PJ I J b @J H|  E K e AL f L( dU L8 fhUU9UULP c0@( d0ULd f0@ d0' c  c0@Lx f T 8U0A& g0@: g  g T P L@- L lU| L@- L dU UU%\UUUD UPpH ht L  L  L  L@-  M pUPP iUP i|UPP j0 UM UPH jL M,  5 oHUPh jUQ hUD M8 Ut8UQ$ hUQ88 h @MT  Ml n( Mx  M  M UQH j M UQ\ iUU&8 AM UQp iUQ h M T M  8 UQ i4 M o8UKU*| M  M m M | N UQ i N  N L N, $U) N8 q ND q NP s N\ t Nh u Nt v N w N w N y N z  QN D N 8 N zUQX iP N z<UQ k4 N , 7@ TUQ jhUQx j N ( O  O  O DUR j @O$  O8  OD 0UK  OP | O\  Oh UK( Ot UR$ k O P O t O |< O U@,0R@ 0P9 l0Q9 0T2 0PRT 0, o @O  @O   P @O  PO 0@< 80U) p P 0) l P 0&p kP0P, 8 P, h0TRp 0%< 0(P  @PD $0*h n<0(< nl0P8  P\ 0A*,   kP T  R@-@ R  R@-P UR  UR , #D U| 1|   X R < R@3pUD    S@-0 B U US  S$  S0 p S< \UUt8 SH    D  ST H #  S` P Sl \ Sx d S  S t S | ! x ! d ! P S  "  8 S  S , S @ S  S  S  S ʈ UT  h  T,      1 D P  @T8 ɀ 8 $ TL @ , 0 TX  UTd l Tx  T   PUT  dU T  4  TT  TT tUXX dUY UY$  T  " ø  x A DŽ T |UY8`  T  T  T  U  U x U  h \  U, P U8 D UD 8 UP 4 U\ , Uh $   8  @ Ut  U  U  U  U  U  U    U   H U  U t "\  "h  "t  1p  1  1  U  1  1 t U d V T "P  "D  "8 ( V  V    V(  V4 U/ V@  VL  VX $ Vd @ Vp    V| ͬ V   , ", 0 V  x  V  V  V  V  " D V  V  " H !  !  V l !  V d !  W X 4 !  !  G|  #t  W 8 W  0UY`  #\  #  W,  W8 UY  WD UZ`  WP  W\  Wh T Wt  W  W | W ư W  Mx X W  W  "  l  W ˰ t  F  W  W | W 0U+ x W ʰ0U%h 0U* X0U*@ 8 X l    8 T  U U| R@3 Z  UZ  UZ P [ ,UD UU   #\  [( l #D Ut8 [< XU   [P   U l x  "   D H 1  \ 8   U[\  U[p  @[  U[ x [  [    "  "  W  V  S$  VL  /  V@  [  V(  V     [  " T # `UT "P  "D  V  V x V p V h SH ` V X V P S D S 8 S0 , V  Sx  Sl  "8  S`  ST  TL  W  W   S  S    l  ",  !  !  !  ! 4 ! H ! \ ! l t ( ! | h 0 !  P D [  #  = D #t  "  \    " ` #  T ִ \  \ ׼ 1| d \$ 0 \0 | 6  \< H \H x Gp  1 X  G| P \T  \`  \l d \x  1 L ;D $ \ ܸ 1d \ \ ݴ 8 L " T ޘ G ި \  \ 4 1 @ 1 8 T  "  , \ U 0   l V ( S    S  S    V UY8` \ D 1p t ;P L \     UZ`   "t x B \   V4  "h  "\  \  @\  @\  ] @ ] ` ]0  P]L  ]d  @]  @] l P] 0U* X P]   X T  R@7U|UD  ^    P  ^  x 4            (0U(( d 5p  ^(  U^<  @^P  U^d  ^x  = X ^ l    ,  8  D    \  h  t x l p " h # ` #D H #\ 4 #t  #  !  !  !  !  !  !  !  !  !  "  "  "  | ", t "8 h "D \ "P P "\ H "h @ "t 8    U   ^  ^ 4 1p 0     1| (U 1   @ ^ ,0U% @0U+    T H  d U tU| R@:  U^ 'U _ UD    _$ . A_@ , #\  x   @U #D  @_\ &( U_t  _ ' |    UU V h 1 $ 1| 8 "\ | "P   \  `   D  U_ , _  \  U_ - [ )Ua4 W "  _ ' _ ' V(  V4  V@  VL  S$  V  V x ! X V X V H ! p ! t # | #t  #  "  l  t  h  P  8  ,    ,  D  L  T  l  | `      #  d !  !  "  "  `   `   `,   `8   `D  $ `P   H(   `\  < `h   `t | `  ` U  H` < `  "   A  At   ",  B(  !<  #, L B  A D !H l #P  A l H  !`  #h  H  H  !l  "8  # @ "D  H 4 H  !x   # d !  !  "h t "t ` 1p L ! 0 A< )  ! D 1  1 UaUYUZ` 1  U UY8` V  S  S  E "Ut8 S  ` & V  " 'p V  ` . T`  T @` *l Ta ,L @a ) a, / PaH + Ta\ "0 Pal $X Pa| .P0U+    T p U AhU| a@= R@@@ b K Ub X(  AX Ub0 _T \ < b@ OUT ! pU AbP b4 Qbh `UD  bx Bh  U b ST #t U Ub F ! \ #D  x ` ,   D "\  "h  "t  !  1|  1  #  h       (  t = Ap M _ b [L V4 $ b U b T8UY b O8 b NP b M| M LD Tb c Tc b ?( H(Ut8 c( [X Uc@ 4 @cT Z Uch CH Qc| [ c FP " D c A ! h ! | !  1p  1  1  1  U t V d S X S P S H V @ V 8 V( 0 V@  VL  S$  V  V  V  V  V  SH  V  V  S  S  "D  "8  1 4` ", ( "  0 " @ ! P ! T !  c > c ?L !0 @T ` @ # A  ` AX #  #\  FH >` # < " p F < l t t  \  "P  !$ ; Uc \ c E P  D  J ;H ;p : 8  J : " :T    c G ;P : ! 9 @ 9\ c 9  c 8 W M8 " 8L L Mx   d NL   d O0  UY` d 7 ! 5 d, 5UY     O R@ Ot RUdxx2 O\ S  0 OP U  <  P J 4 A Z d8 _ @dD `0U+ 2H  2H T 0 R@C` d l Ud v t  "8  ?p q\   d g  4UD   D  UU H w ( f d t Ue f0 @e s Ue0 h x PU| V T ;P t eH g ! (     eT h !     # < 8  ! Ut8   el i 5 i Tex w ?@ k   e n   S$ X  < V P V H V @ V < SH 4 V , V $ S  S  S0  V  Sx  Sl  W  S`  ST  TL  W  W   S  S  W,  W8 | WD p WP l W\ d W \  d W T # w8 W H S < S 0 \  h  P  l x " l # h > d #D ` #\ X #t P D  ,    !  !  e f   / f 7 g !  !  !  !  "  "  "   ",    "D p "P \ "\ H "h 8 "t ( 1p  1|  1  1  1  1  U  ET iT V  S  ? k ; lp S  S  V  V UY` V( xUYUZ` V4 p V@ h c o` @ o ! o VL ` `P tUY8`0U,8 dH e t  dH T  R@G e  Ue  M |,UD  "  UU  < t  x 1p h e \ Uf z @f( L "  Uf@ | ! TU|    H fX |L "t lUt8  0 fl } " P  ( !  "  "   h ",  "8  "D  "P  "\ x "h p  p  x 1| ` 1 X 1 P 1 H 1 @ U 8 V , S  S  S  V  V  x  V(  \  V4  V@  VL  S$  V         \`  ,  8  D  P  \  h   T 74 { fx { e | l   X #  #D  #\  #t t # h ! \  ` ! < ! ( f }h !  !  !  ! 0U, y f ~    y T @ R@J U  .f U Uf U| -f UD  d Ua l     `     f LUa ! Uh   U | ! t   P V  P , G      T ( g  g U Ug,  @g@  UgT  gh   Uhh T,  x  W UY H  @ x 1  V H V( @ V4 8 V@ ( VL  S$  V  V  V  V  V  SH  V   t S  S  S0  V  Sx p Sl ` W \ S` L ST < TL , W $ W   S  S  W,  W8  WD  WP  W\  W  W  W  S  S      W    U t E  U h U  \ S< T U, L U8 D UD @ D 0U \  h  t  8 < "  #  #D  #\  #t  #  !  , L !  !  !  !  gt X  \ Jx  ! l Z  ! d g  g  Rg  =d @ g  Qg  I P g  >  " \ " DU "  0 ",  "8  "D  "P  "\  "h  "t  g h 1p  1|  1  1  1  1   d V t g X S lUZ` S d S X !$   V P F h Pg h lh 0 Ph( | @hD d lh`   h| \ h  ,h 0U%    T ` R@O h U| M UD  h       4     D    ° h  x @ Ui  `8  @i0  UiH t  $ V UT l lU 1    P Œ   i`  V(  J  " l "  d ", ` "8 X "D P "P H "\ < "h 4 "t , 1p $ 1|  1  1  1  1  U  V  S  S  S  V      V4 | V@ t VL l S$ d V `  ,  TU 8 œ , ¬  ¼ \ € h x t p   " d # \ #D T #\ @ #t , # ( !  ix  !  !  i x i l E p i P i 4 i  "   i P Qi  i  `\  [  =  ! U !  ! UY ! UZ` !  ! | H(  " t i   ] „0U%    T Ű d U| j@V 0  Qj  R@R j4 l jD@V jP@VU< j`@U jt $UD  j@  Ʉ j   Ɉ ! ȌU h    j UT "  x   X @j d @j  Uj l j  k 8   k  Sx  S 0 S$ Ơ VL ƴ V@  V4  V  V  k,  , kD  kX U&8 ! L  ɨ b   ɸ "  "   Ukd  Ukx  k  k   t 1 h 1 p 1 | 1| Lj 1p ǘ "t ǜ "h Ǥ "\ Ǵ "P  "D  "8  ",  ! $ ! 8 ! P ! d ! x ! Ȕ ! Ȥ # ȴ #t   ɔ #\  #D   ɤ #  "  l  t  \ $ P ,  ɴ OP  D 4 8 < , D OD ɰ O8    L O ʌ   O t N ˨ N  N ̴ k  h N @ N, ͐ N ΐ k \ k D k а k  k  k Ԡ Ul  l $ l H l,  l8 0 lD  lP  l\ \ lh ج lt  l T l ۘ l  l  l , l ݔ l  l   l \ l  V(  l  A0  m d m  m \ E  b d m(  m4  6 $ m@ 8 mL \ 7  S  mX , md  A  A d mp  S 0 S @ V Ɣ V ƈUYUZ` V | Am| l V t 7L  7X  7d < V l m ` SH d V ` V P S @ V P S0  V  U X Sl  W  S`  ST Ű m  1 ` m P  \  h Um \ m H Pm  0ol 0o ` m   @m  @n  Tn$   @n@  PnT 0U*T Ā Pnh  4 n| 00To  Pn X  Ā T x o@V o@VU| o dUUUUTUD  o Ut8 Hl 0p @0UX ` o ,0U& 0XP X0TY 0PX 0%$ 00@p, 0Tp@ 0)   0 T  R@VU pT %D ;| )UUTUU Uph <UXX Up ' p ,XU ( 5| $0Uq\ !, p $Uqp, i & i '(U| Et )U$  @p * Tp ) Ap )$ Up HU X` 1 !     q $       \ &x   1d 'UUD    x  q ' q + ! (\ q0 ( " (UY`   q< 0$0@V  H T  q@ q@ q@  q@ q@ q@ q@ r@ r @ r4@\ rD@ rX@ rh@ r@W r@U 4X, r@ r@W r@ r@ Ar 2 s 0d Qs :U| Qs 0 Qs4 5U h 0\ QsD 1x M .0 QsX 2 5 - Ush 3X ^ 0PU Usx - Us , ;8 -0$p@W    , T ؈UqpUtx< Us BU ( 1 BU 74 ?\ = C o DxU| =d C< VX C s ?XU X` Us  , yp U}xH y|  y  l  y  Uy Ǹ y \ Uy T S<  U,  # T " ` l  t  h  P  8  ,                0  @  l "  d ", P y  " x "  !  "\  "h  "t  1p  1|  1  1  1  1  U  V  S  S  !  V  V  V( x V4 p \  Q]  " < V@ h  G  VL ` Uy  Uy  !  !  V 0 !  ! 0Q~@ < !  ! $ V  V  S  S  S0 UY8` ! ( Sx  Sl  `P  W  H(  S` t ST l TL d W \ #h  W  T S L S DU  W, < E   # 0 WD , WP  W\  W  W U|hd W  S  k p S  T,  mX p W  z À W  U  z Ĝ U  #t 8 P]  Tz$ ,0U%    T ( @ސ @_ @U| U, hUYUY < UD UU UU8UȘ0 x0Ta 0TZ  @H 0Ta h TX ؜ h l0TX 0TZ 0Q 0 (0@Xt 0 Ϝ0X8 Ϩ0TX 40QX ϰ0Q    T 0 @_  |  t  l  `  T  L  @  4  (            ,  8  D  P  \  h  t  l  "  # p #D ` #\ P #t @ # 4 ! , !  !  !  !  !  !  !  x  ! U%\ "  "  "   ",  "8 | "D p "P d "\ T "h D "t 8 1p , 1|  1  1  1  1  U  V  S  S  S  V  V  V( t V4 h V@ \ VL P S$ D V 0U0HU@@d0A6 0A5 4  T     T  @ @`0 T@ d@UUxU t  G  y TU:, / @Uxh e U`UhDU ; UU0|U%\UwPUhU:D @ h0: D 00AZ0  P p0A9 80Q9 0Ax 0 `   T  !x  \ | 0 D J UU U< X UP UD  G @ U` | !`  Ux  !H  VX  @ H ! X ;P hU| "  J   ;p L J  !$  F \ #  T 8 FH  c  c  !0  ` $ #  #8 ,Ut8 # U H p W  Mx  T  E     $ H , 4 <   JX 0UYH 0TY D0UY` 0UY @  @ h@`8 T  G  A| $UU R U0> 0U>@    T  @ @`@ @`H @`D @`L @\ @`d @H0U] UaUUU0dUUHh,UYU\hH 0Q$ 0 P0T]  0<   T0Td`  0TZ 00TY    T p @ @`x T@U0U xUUUxtUh0@X( 00QXd  l    @0 @` o  @ H    @  1  g UU  ^ t f  ?|  5d 0PC 0TF 0@Z   0PB 0@B  T U|UD UP0U]   0TZD  T  @`UU|  'U(0 o !       x U:D i 'U%\    U   5 #UTU<  UD 0@^ '\0U^ 0Q^ %  0@w (    T X P@a d@aU @| 6` el /  0`U%\ = 0   9,UUUK UDU( U ;4UQH U 9t M + h - ?@ 0@ !l <<UD  ` :U l( 4 6( " 5 5 6 ?4 , 5 + e / o /l 2|  8 Hl /L G 5UK H <0 \ 6 p .U)  7( . !< :U@(Ut80UH )( @ 00@; -00< *  )( T p ,@b <@b L@bU8UH>U R@a X c l b  a8 ! X0U,>  Bl U B y @ = MU>T R MU>U> Q PU= R<   U ? U  t U A P E T I  | Q RdUH= U, dUX(= l@ Z lP [8   d M             E O   i P| S ? i P   x    h A " W J X  eH BT p@aU  p0n@bT  [ @ E  ?  T  R@bU U l U l > k           y k,   U j U k P m T p R q Q rd U, t$ lD s lT s x  p@b   6 l M lTUXXUY`U0n@c| @h nH  j T  R@c U { > z U { T  U z Po | T ~ R \ Q ( l X l      x    y yUU p@c M { 6 {h U0 yx  U0oD@d\ @@ |  yx T 0 X@fx d@f| t@f @fUU R@d U A  U t U H U U \ ,U  8 0   D  U `     P $ T  R$  Q4  UD  l\   ll L x    p@d U `     @    @d  x  pU  h  d M   T c   P  D   < , 4 U  @ 0o @f(  ` T 0UU R@f Ud  i    Ux UYU \  Hl  U  l  l d  p x |   R  p@f 6  \0   P  D  <  4  0  T  U U 0U  d 4 0  h P   T  R $ Q$ P @8 0o0@g0T h  0 T U x ,U P l0. | R@g Q\ pU|UU (UwU X` t lUPH \T 0UU <PU 0X4U@lUU    U                T |0U $ \ UL \$  \0  6     UD  \`    U l  U)HU}xU&80UT  00Q H0UoT h0Q L0Q |  h0T4 Ș T U R@iU U @U|UD UU lUt8U UyL `  > @ Q < U  l x l  U$  P8 L UL p T\  Tl   $ x ,  4 p@i y |   M  6 (                    <UY U U   G ڜ U d P U T   R x0o@j @ | PD    T U G  G UU0@ 80 d0U l0Un 0Uh X08 (0, 0, 0  ( T  @ < R@kT 8@ld U d   UL  $ > d Ud X   Ux  P  T  R < Q ( l X l      @ P @  x     UU   M  7(  6 L y    p@kH0n@l @<   X T 0n@m< R@l| U  UT U g  Jx $ Ul  U 4 P  T  U   l   l  ( >      R  Q  $   R$  Q4         x  6 t   p@lp   M UYUHUUppTUX( g  y D I U @D 0n@m   T 0{@n$0{X@n0zH@mUU0z@m  0{0  6Ut8  @ < . @ < A ; Q ;U l  /P $ @ 0 6 < /0~  x 0{ $ @H ; A\ :, Qp : Q  h   .LUD  Q  .h  /  5l A 9p  5  60A|l )D0}$ p0T #0( &0A| * P ,0@< 0PT    0T|T !0p -0@~l l0T{p ` , 0 H D P\  x   7 @ 4  0~ d0@~ P0{ 9`0A} ,0 (0~ =  p T   \ A ~U @l A D @p @h xU T UU|  c 80 r 7 tlUD  p` Hl H , w0Uwt 8 0 Ah | D ~ G H @P  Ah   T| ` U  GUZ` A\ pH A ? 8 q sUYU x `  u( u v wDUwpUw  L  |P  ~ U lUwdUX(>d ( I0}8 >0U} n40U} y0T~T d$  > T4 T0U} p TP R0P{ e @d r x K T 0Tl 0U}P 0U}d 0 c P { @ d @ Dx0U  P |0T|@ f0| h0U} t T l T Q0P{ j@0~ ?L T U|U ix 80Uz H0A{  t c ` ;P ` `   p  \  \x  5d  A U At  A  `  [  =  \l  ?| P ;| 0 A  U%,0Pz `0A{ 0Uzp X0P|  0@| T0A 8  H T x0@nH0@nhU| f 8  4 U$ hUD  A8 \ QL T \0 H @`  =  u0 \ i 0T  @t  G  0 Q , 5  ?4 | Gp UU Z ,0Q{ ` G  Q   x 0U}x 0Q 0P|    T U @nU| h  Q  \ U0A|,  \ @ R   H    A |UD    D    8           ,          0 #  P  FH   c    c   !0     ` ( #  `  ` ` x @ `, h `8   ,U0 8    L0@| P0@, 0@~, 0U}  @  P    T  R@q@ <@q @T H l@q  Ҽ 8 ix ьU|UT   T L G  ф T  @ Ѩ 5  ̈ U \  0  nj      U   ;8 ` M < ^ `   Z (     U  U4  H@q4 ( ̀UD  T U @X   Ul ͨ A ͜ Q   x  @ $ @  f 4 i Ш [ а = `  0U} @0Q   @ T x @ @r  @ @ d@xUxh d քU M 0AT 0U< Ԙ  0@ h0Q h  hUwp AX UZ`|UpؼU9ؘ0UD    T !`U @r(UHUU, ; 0Qt  0A\ 0Q P  FT h0Q H TU80R H0l` `0. 0@ 0TH L0RL 0T 0m, 0P 0U    T "Uxh @r0UU$ 8U@ 5 UUU@8   %  %  %   % , % 8 % D %p P %l \ %d h %T t %H l %< " %0 # %$ #D % #\ % #t %  # % ! $ ! $ ! $ ! $ ! $ ! $ ! $ ! $ ! $ " $ " $ "  $ ", $| "8 $t "D $l "P $d "\ $T "h $H "t $< x &P 1p $0U 8T 1| $$ 1 $ 1 $  1 # 1 # U # V # S # S # S # V # V # V( # V4 #| V@ #t VL #l S$ #\ V #L V #8 V #, V #$ V # SH # V # V " S " S "UT  &<  &,U(U,x  &$  &  &  %  %  % =   %  % = H0U p  &X0Q$ p0 $  p0D@t T '(UpUT|U0`0T 0`    T '0UU x@w @tUTU h  0AZp      el  L `h  FH 0A 8 D i  gh  M  8 ( D ( P ( \ ( h ( t ( l ( " ( # ( #D ( #\ ( #t ( # ( ! ( ! ( ! (| ! (t ! (l ! (d ! (\ ! (T ! (L " (D " (< "  (8 ", (0 "8 (( "D (  "P ( "\ ( "h ( "t ( 1p ' 1| ' 1 ' 1 ' 1 ' 1 ' U '  V ' S ' S ' S ' V ' V ' V( ' V4 ' V@ ' VL ' S$ 'x V 'p V 'h V '` V 'X V 'P SH '@ V '8 V '0 x )x  )p  )h  )`  )X  )P  )D     )<  )4  ), 5p  8   )$ $ d  )   )  )    ) , (0AZ 0Qp 0Q ,0U @ 0 t0U 40@ 0)L h0Q3  L0@  0@ 0T3  00P  0P8 0U0 0   )0A , 0AP @04 P   T + l@w  @w @wU @w$ @w0U @w( @w< @w @w, 0 1 `t 1UD  @@w8 @L # h@w @ #U|Ut8 @ T  $ @  U 48  ) UT @ +8 E 3  A4 $ ?p %P AP  T * !l / c ,L H /  \` ( l (U0U , @ 2 A 1$ `h . Z !|U&8 0 G / H / q0 * / . F ,<U  ^ % t !l0Q  \l ( - - 3  2`0h &0| &0@ +0@< &$0@ V < A = \ K4 y T<U  ( T  < Il N U  4 M DU0 I0U K0P <0 :0Qh H  9( T 0 @dU| WU&8 " XUUD  5 X e W0Q9 V0QB Xx0QC Y  V T 1UUD UU 8 ` AH e@ AX a Ah cD Qx ` A `8 Q ed Q c Q bH03 ^ Ut80 ^h0A2 ]0)x ]P0@ \(0 \  e  \( T 3 UTU| @w\ @wXU $ x 0@wx D@wpU X@wh @l \ @wlUD  @wd0 h`U @wt @w| @` @w` i qh Q$ q8U  @8  @T  Ap \ `  0AD t0Q| mpUt8 v  i fx i !` x  | J p t  z\ {  o  t Q | \ sh @0 8 D  d  5 k Ap vp @ k  j<  { d  4 =p p0U  G r \ r \ r Q s T sd g k0 0   8 i  < T , w 8  D  P , \ U0Hg h  t    A p  5 o ` U  d w0P p@0Ah pH0 ph P pp  p0U n0A l(0 0 0@ ,0 H @ y0QD 40A8 0QH P0d p80P| 0QD 0@ l0@ h0@ yl0P i$0U 0P ip0U 0Q v T  P8 0U  PP 0T   h T : @d @@wUT0q U > $ UU UL (   = \ u Ut8 G  ` , /  ( T ?d  4 | ? p ET LU(`U0U4  @    0U 0 l0@ 0h x0A 0U 0Q 0   ( T ? U, LU A@ Lj  hU / \Ut8UD U 0 P P Č ^  ^ l0@t 0@)d x  h0U' h @w @w0@w @w @ @wU Ml $  ʘ " p ^ hU  00X ˴0@; 0  p0@( 0P$ 0P0| p0   T @U| G U A 0 Q0 UUD Ut8 AH  X \ P U i  gt ӈ 0U' UT @  5 Ш d x0Q'   ;D x \  1d T \  " | ش G 0U ь0 x    p@ @w @wU T C   " (U ހ L M 0<0 80@C4 ތ0U| U )UP'UX(HU x0(d U 7 Q : @ 9 U *d @ < `h <0Q /  /8U) U& 1 .U&U@'LUX& Q 5l 4 1 U@ 4HU('hUh'UD ' UT 3U' Uh 4 U| 2p 7( /  J(UH(U$(,UD(U<P( U ,Ux' J 9U xUp(U p(U  x J  U +t `t <UP( U * #, =0U\ <@0@t +  J0U 1h0Up 00U :0 ><0t ?(0 ;0UD -0U ?X  )( @ @ @ T L0 @U xU@ D  B @ E 0Yx C0A0 A0P B0@/ @  @ T L (@ A8 P D@x  P YlU A\ S ET LH ` SPUD  Ql G Qt St A I@ G G G `D STU| A JhU A L A X< ` R H` Rx @ K ?| KUE< ` R` 1 G 1 I @ Q @ Q0` EX @ Q0QP R00 Y P Q40 Y  EX @  @ $@x( 4@x,UU  Y0D Z00Ah ZP0AX Y0l Z0T [p T M @dU|UT  _ Q ` = _  a| 7( aU U aUD  1 ] Hl aU&8 ?@ \ ET `U[U[U[0Up [  [ T P@UU| 5| v UUU(` Mx {,UD U&8Uc > k 5 ml g il k  5 h( fUT  y0 yp { , ~ U c l @ \ ,Uhc ! m 8  # mx D n  P oP \ o p $ q s c s gh t4 Qh vU z g i H z { 4 k0 | ~ = f ?@ g `U`c 0U {T0U k0UL dD0U j0U jP0U i0U4 z0U ~0U h0U ht0U h<0U( g0U\ f0U8 d  d T V` @x4 @ @U| 0@ D@UTUD  `, ( o P0@x0UU J   P  \  k H h Ah H $  c  X  c  4U | U  B@ D Ot t l 0U0U  fl U L0U 0U 0Uh 0U| 0U 0U 0U ,0U 0U l0U P0U4   0UD  T _ UTU|UD UUU yp  U U}xUt8 T  ( l  P L 4 ݘ 0 X  @ ɤ L l 8 Ӱ  X  d < #8  p U)H G|  g UU X | @U t Ӥ d 4 Ä  b   X0U ,0U Ш0Ut 40U H0U 0U 0U 0Ud ״0U` 0U \0U, L0U@ 0U 0U Ĭ0U ߨ   T hX @x8 (@UUUD Ut8 U< 0 AP  d U =   U|UTU 0 0@ , t 0 x0 0 x   T h @d U  @x@ U 0@y@ UT @yHU Q  @x Q0 T D P UP P d UU&8  iU Qp  7(  H  ( T  h   X 7 <  i  ! i  i$U00 ! iU<@ ! iU ! i  i(U, ! iUH ! iU8 ! iUT( ! iU` ! iUh " iUh " iU "  i|Ut  ", itUh "8 ipUw\ "D ilUH "P idU| x i, "\ i\UU "h iXUˆ "t iPU 1p iL U  1| iD U   1 i@ U   1 i8 U  t $  i  i  i   i  h | UD Ut8  h   h , h 8 h D h P h ;p @ J x Q 0 \ h h h t h l h " h # h m  #D h m  #\ h #t h m  E 8 b  m( < m4  # h  i A    i0Q 0Q 0A 0T 0Q ` @ 0, t0@yD  i0   T lUUD U|U 4 pUt8 A$ U l  eH t0Qð  U T U&8U|h \ "  i   i  i   U4 X [  QD  1d  7 hU @T  d  0U  @t  @Ä  Ô h @à `    T oUU| U $4U d < @} @| U A  $@}UD  < < \` 0 @H E  d@| | @UTUt8 UĈ ,TU Ę F @Ĥ Dd 9L0A 2 Q 1 Q %0  @ U =  C 8 " QH 1 \ /P 5 + " p4 "  p, ", p$ "8 p "D p "P p  "\ p "h o "t o 1p o 1| o 1 o 1 o 1 o 1 o U o V o S o S o S o V o ! p@ ! pH  q\0U ! ! pP  qd ! pX ! pd ! pl x ql  qL ! pt ! p| ! p # p #t p #\ p #D p AX *@ Qt (4 5 +D QŌ + # p " p l p t p " p< h p Ť F \$ -T \ p QŰ / P p D p ;D 08 \ 0d 1d 0 8 p , p Q 3H   p  q  q   q  q  q$  q(  qT  q4 ?d 5p 6 yp 6  q< ; , ; ;   , >t0@ FH00 F0 E0U 40QD F  qt0AX F0l GL0Uƀ G0UƔ HL  ! T zUTU \ adUUD UU| X O4 @ƨ ] E X( `P ] \0 X u cL  ` #h _ T _ q V , b H _ 4 UUt8 T W `h \l 5 N cL b \< X b0U O`0U Q0U0 S0UT U0U8 V 0U V0U L0U \$0U M0U@ `L0UL XL0U J0U X0Up [h @ ^ @( ^   J T 0UXUcU` c0A( d0UL c  c T ` t@}UU @LjnH ǜnpU}xUt8UD  @iU)H hUT0Tl 0UXe0Am e T 0@}0A\nUUD Ut8U0Uœp iw gts0U,r0Q G~X0@<y 0Qy A|D A~d }x gs| "wUU U&80U°s ~T0Upu0< n T @dU|0L0`00  T @U UD 1UD UUt8 T M 7(U00QUT  =| 5< FT0 h0Ad0UH0U4 H T  x@8@d Ȉ@@ Ȭ@<UD UUt8U pUXUU < U@U(`U UUU( UxDU0AUUU(`U UxU80|UDUP@040``0U`<0Q0Q0Ut0Ʉ00U0A0A U d( T @@dU  Aɜ8 1 RUD 0AU ;X ,UU0UUp HlTUp<U  t oU8 p( ɰX0U0U X @HUUU8P0 00H0 T  D@ X@ h@PUʀ` U d(0(  0  ( T h ʌ@0 @ ʠ@@00@h ʸ@, @( @$0@@  @  @< @ (@00P@ <@ P@0`@  d@0p@$0̀@x x@  ˌ@8 ˠ@0͔@ `0ͤ@$0ʹ@0@\ ˴@40@x @( @0@H @T @ @ 0@X @@PUT0@0 @0@$ T@,0,@ h@0<@  x@U0L@UD U ǓU  JXU  A̘P "t  1p  1|  1  1  1  1  U  V  S  S  S  V  V  V(  V4  V@  VL  S$  V  V  V | V t V p SH l V d V \ S X S T S0 P V L Sx H Sl D W @ S` < ST 8 TL 4 W 0 W  ( S  S 0\@ W,    W8  WD  WP  W\  W  W  W  S  S  T,  W    W L U H U D U  @ S< < U, 8 U8 4 UD 0 UP , U\ ( Uh $ Tx  T  Ut  U  U  U  U  U  U  V  Vd  U  U  ̨    U̴           QT Qp  U}x    U|   l    ,  8  D  ` P  \  h | t t l h  $ "  # x #D l #\ d #t ` # X ! P ! L ! D ! @ x , !  !  !  !  !  "  "  "   ",   8 "8  "D  "P  "\  "h 0tp Ǽ  0Ut0Έ@ 0Π@  @d0    @H δ@U pUʀ`Ut80` ` T UU0Uǰ0Aې 0@ 0@x @X0$UP۴ 0\ 0 ܘ0t@   0ψ@0< 0Ϡ@0D@0Ϭ@0@0@0ϼ@0@0@@02@@0@0p@0@0(@ 0px 0ьx 0ќx 0Ѭx 0Ѽy 0y hy0 ty ЀzL 0yG 0y_ Ќyp 0y 0 y Иy 0y 0,y Фz 08z/ дz@ z\ 0<z z 0Lz 0\z z 0lz 0|z z 0Ҍ{ { 0Ҝ{3 { {4 {D {l ({x 0{ 8{ H{ P{ 0Ҭ{ 0Ҽ{ X| 0| 0|; d|D 0|? 02|W 0@|S ~ }| 4|\ 0H~ `~4 h< 0 O ӈh 0( Ӵ0(G04@0@@80HG0T@0`@800 J l 0P  < x & h) 89(ʀ( <X}  [D0 0XEX\ qpH <   h  9()()(  < d  L X $ l )( X d t\ Q kPQ\ kP0H *<34 -48 - xhH8)(Q kP,P ,d 0p ** R$ kP9 [P kPpH .@ @+$ P kPX 8Y 8P kPwH83` -wtH8*| aQ kP>p Q kP? Y$ 8Q kP? Y 8a,$ R kP0 *Q kPxH8@, 3H -X?  p)((t P kPQ kP; H$ + :, [>, LP cK EQ$ kPZ` 8xH80' ) :D [? `2P -; K E,p wH8Y 8$ K E(:p [pP kPwH8+ :X [\& dx2H+ x0* +T  @ QH kPh/ *D * xH8%\ 3 -> K EwdH8H? Qp kPxH8X>/ *Q8 kP@ Pp kP@@ 4L -xXH8,p, * 0A 0 0U'x [ Y0U'L \ Y0U'8 _ Y0U'$ U P0U' bd Y0U& @0U& 0U& 0U&0U&` b Z 0U&0 <0U& 0U&  0U& c Z$0U% 4 .0U% d Z<0U% e ZT0U' h Zl0U( i Z0U) p g0U*@ 8 0U*TĀ0U* X 0U* X 0U+ 0U+ x 0U+(0U+2H00U,8dHcH0U,yx80U%h 0U%0U%0U%0U% @  @B  @A  @E  @E  @G 0 @G H @O$ g Up L Ap d Tp | @p  q  Us , Usx , Us ; Ut ; Us ; Uvd Eh AvT E Tv@ E @v, E v E0Ul0UhX U < U < U < P < T < Q = Q =$ U, =< T@ =T TP =x U iT U il U i P i T i Q i Q i U, j TD j TT j@ U0 x, U xD U x\ Po xt T x Q x Q x T x T y U  U  U  U  U  P 0 T H Q$ ` Q4  UD  T\  Tl  U  Ux  Ud   P $ T < Q T Q$ t U  T  T  U 4 UyL L U d P | T ˔ Q ˬ Q  U  T  T   U$ D P8 \ UL t T\ ̌ Tl ̤ Ud  UL  Ux  P  T  Q , Q L T d T  @  @  Ul  UT  U 4 P L T d Q | Q  U  T  T  Q$  Q4 4 A  Qp  A\ 0U= @H  Q  A ( @ @ @ X QL @ A8 X U$ p @`  @  @  Q  A  Ul 0 @X H U4 ` U x0U\0U40U8db@0ULdDbX0U\fbp0Up[[0Uh<b0Uhtb0Uhb0Uib0UjPb0U jc0Uf0U4zc0U{Tc00U~cH0U|L0U D0U0UP0Ul0U4!0U,0Ud0U 0U 0U4 0UD80UXeeH0UhP0U|h0U0U0Uь0UH0U\0U 0U$0U<0U,LT0U@l0UP |0U`0Ut40UШ0U,0UH0U d0U40UT0Uߨ0U,d0U(gc`0U8V IP0ULXLIh0Up[hI0UVI0Ukcx0ULI0UMI0UK80U\$I0U1h%P0UJI0U0U O`J0U0SJ(0U@`LJ@0UTUJX0Ud״,0Ut4H|0U3D0UQJp0UXJ0UĬD Ux %h U % U % U % U % U % U| % Uh & UT &( U@ &@ Q &X U @ UP X U p U  U  U 0 @ , 0H 0  \ 0 80U Ŕ 0 Ѐ 0 $ 0 p 40U\ !0 $0L ! <0U4 # T0U ) l0U * 0U #4 0U8 , 0U( + 0UH ,x 0U ' 0U ( 0U < ;0U H ;0 Ih ;0Ut ,0U " D0U " \0 p t0Ut , 0U - 0U - 0U .p 0UX /x 0U0 . 0D /D 0U -l 4  0U$ Z @/ ) @/ ) @1P ,, 4 P U5L P U54 P U5 P U6 Z @6 Z @7 Z ; T A;\ l @=P X A?  A>  @  @A  AH 8 E  @E  E 0 @F ` @G8 x F  UH4 ., HL .D QHx .\0UK4 O D, I DD AJ@ D\ I Dt @J, D AI D L( cd K c| AL c L8 c @MT h L h, AM hD L h\ S 4 UT L @T8 d R | UR  UR  TT  TT  [  U[  @[  U[p ( [ @ UZ X [< p [ ш [( Ѡ ^x 8 U^d P @^P h ^  ^  ^(  _ @ U_t X @_\ p U_  _$  _  _  c( 0 Uc@ 0 @cT 1 bx 1, b 1D Ub0 1\ Tc 1t Tb 1 b@ 1 c 1 d c` Ue cx @e c Ud c Tex c d c eT c e xP Uf xh @f( x Ue x e x fX x g  Ug,  @g@  Uf  f  g   h  Ui  @i0  h ( i` @ j  Uj   @j $ @j < Ukx T jt l kD Ä j Ü k, ô p  Up  uT E Uup E t F u F( y  Uy  @y 0@|Pl Uy4 0|t y`  y 0 A| | @ 8 @ P  h  (p @| (  ( T y$ @   =0T T > @P > Ah >4 T| >L @t  A  @T Ð  è T  @  T  AX d0U$D  h0@<y n @  @  l  AP  @L   @ $  < A4 T @ l   @  0  U   6  8 A [h Qx [ Ah [ AX [ Q [ Q [ AH [ Q \ @ g  @l g$  g< @0 gT Ap gl Ap g @8 g @T g D g U, @  ۴ @ &p Ah  U \ U<  d  U !   !8 U !P @H !h  ! @Ĥ ! @ƨ J T J  J ǜe` @Ljex T UD0  0<0$ۜ L  h  h  L ` w\ G  ȴ   , >8 >p > > Q > T@ ? TP ? Q jt TD j TT j Q y< T yX T yh Q$ $ T\ @ Tl P Q  T  T   Q  T  T  Q  T 8 T H Q p T  T  Q$  L main __text_start ___stack_zero __data_start $START_RTN$ $str_lit_sym$ $THIS_DATA$$THIS_SHORTDATA$ $THIS_BSS$$THIS_SHORTBSS$$THIS_STATICDATA$$THIS_SHORTSTATICDATA$ $THIS_LIT$$THIS_LITSTATIC$$$stat_0 __map_dlderrorstrlenitoa__exitsyserroropenclosereadwritelseekmmap$global$$START$$ARGV _fp_status_start_mcount_clear_counters _sr4export $UNWIND_START $UNWIND_END$RECOVER_START $RECOVER_END __dld_flags __dld_hook __dld_list __SYSTEM_ID _SYSTEM_ID $PFA_C_START $PFA_C_ENDerrno_etext_end __dld_loc $$dyncall $$divI_10$$remI$LIT$downarrow_bits phone_bits mail_bitseye_bits audio_bitswb_bits text_bits unknown_bits clock_bitswww_bits tick_bitsucl_bits cross_bits tools_bits bullet0_bits bullet1_bitsbroadcast_bits meeting_bits test_bitssdr_bits uparrow_bits L$text0000 L$text_end$CODE$interp Tk_GetUidTk_DefineBitmap init_bitmapsbuf___2__iobusernamehostaddrfprintfstrncmpstrchr ui_visibleperror busrxsockgetpid inet_ntoabus_sendis_a_bus_message bus_listen inet_addrsocketatoiconnectbus_recv setsockoptsendstrcpyparse_bus_messagerecvfrom Tcl_SetVar2 sip_listenrebuild_interfacegetenvsprintfbus_send_new_appbzerobcopybcmp last_addr first_addrstrcmp check_addressrandomdelete_address store_addressfree generate_port gettimeofdaymallocgenerate_address Tcl_GetFileTcl_CreateFileHandler linksocketTcl_DeleteFileHandler unlinksocketrandseedsrandom namestr___27last_adfirst_adno_of_ads___38buf___21 done___14 debugbuf___22set_timedebug1 Tcl_SetVarno_of_tx_socksdoexit rx_sock_addrtxsockrxsock tx_sock_addrhostname rx_sock_portloggingno_of_rx_socks siprxsockguiexitprintfmemcpyenvrfd2sockttlTcl_GlobalEvalclean_up_and_diesscanfsignaltimed_send_advert parse_entrycheck_net_typeTk_GetNumMainWindowssd_txxremove_interfaceload_cache_entry recv_packets extract_ttl send_advertTcl_Evalget_pass_phrase sd_listenstrncpystrcatqueue_ad_for_sendingui_create_interfaceTcl_AddErrorInfosip_recvTcl_CreateTimerHandlerfcntlTcl_DoOneEvent gethostbynamegetuidgetpwuid setlocaleui_init initnamesbindseedrandremove_interfacelongjmpTk_Initdumpdecrypt_announcementmemset init_securityfclosesplat_tcl_special_charsfreadTcl_CreateCommandfopenwarn_tcl_special_charsXSetIOErrorHandler__mainsetjmp$$remUload_crypted_filefind_key_by_nameencrypt_announcementTcl_DeleteTimerHandler gethostnamestop_session_ad force_numeric siptxsockL$C0023L$C0001L$C0002L$C0003L$C0004L$C0005L$C0006L$C0007L$C0008L$C0009L$C0010L$C0011L$C0012L$C0013L$C0014L$C0015L$C0016L$C0017L$C0018L$C0019L$C0020L$C0021L$C0022L$C0000pluginsplugtut mbone_faq mbone_toolsbugschangesintronode1node2node3node4node5node6node7node8node9node10node11node12node13node14node15help no_of_helphelpdata sockets___9str___13 addr___12no_of_socks___7 slist___8 username___16 Tcl_VarEval__ctypelook_up_addressparse_sip_replyis_a_sip_replysip_get_dstnameis_a_sip_requestsip_sendparse_sip_tryingparse_sip_successparse_sip_failparse_sip_progress parse_sip_faparse_sip_ringing res_mkqueryres_send dn_expandstrstr send_sip_msgTkCreateXEventSourceTkPlatformInit longmonnames email___24monnamesdaynames longdaynames save_keysui_generate_address generate_idui_generate_port ui_sd_listenui_quit getdayname getmonnameui_sip_send_msggetemailaddressatolui_check_addressui_lookup_host createsession getusername gethostaddrui_stop_session_adset_pass_phraseui_set_passphraseui_get_passphrasewrite_crypted_fileui_write_crypted_file register_key ui_add_key delete_key ui_delete_key load_keys ui_load_keys ui_save_keysui_find_key_by_name mainWindowdisplaygeometryargTablecommandnamefileName synchronizeannounce_errortcl_sdrtcl_new tcl_sap_crypttcl_www tcl_generictcl_libstcl_siptcl_sdp tcl_pluginstcl_parsed_pluginstcl_start_toolsstrncatwebtosave_www_data_to_filestop_www_loading Tk_ParseArgvTcl_CreateInterp Tk_MainWindowfflushTcl_DStringInit www_perrorwebdata webdatalen webblocks stoploadingselect getsockoptreallocrecvstrerrorfwritekeylist passphraseSet_Key get_sdr_homestatEncryptDecryptfind_key_by_idMD5Init MD5UpdateMD5Finalchmodrenamedes_key badpktlen_ empty_keybadpbit_ install_keydecryptwrkbuf_qfDESNull_Key crypt_bufferPADDING MD5_memcpyDecode MD5TransformEncode MD5_memsetkeys___5s_p0s_p1s_p2s_p6s_p3s_p7s_p4s_p5 oldKey___4 oldWhat___6rolror oldMode___7 desKeys___3 desKey___2 G_padChar sys_errlistsys_nerrqfDES_insertPadding qfDES_malloc qfDES_realloc qfDES_free qfDES_bin2hex qfDES_setPad qfDES_hex2bin qfDES_copy buffer___11 flag___12weakKeyskey___6qfDES_checkWeakKeysqfDES_checkParity qfDES_str2keyqfDES_setParitymemcmptimeqfDES_generate defaultTable spaces___4L$0079L$0004L$0097L$0098L$0099 PrintUsageTcl_AppendResult Tk_AddOptionstrtodstrtol initializedidTable predefTable nameTable dataTableautoNumber___12 warning_bitshourglass_bitsL$0006 error_bitsquesthead_bits info_bits gray25_bits question_bits gray12_bits gray50_bitsL$0013L$0014 BitmapInitpanicTcl_InitHashTableTcl_DeleteHashEntryTcl_DStringFreeXCreateBitmapFromDataXReadBitmapFile Tk_GetBitmapTcl_TranslateFileNameTcl_DeleteInterp XFreePixmap Tk_FreeXIdTk_SizeOfBitmapTk_GetBitmapFromData Tk_FreeBitmapTk_NameOfBitmapuidTableTk_NameOfCapStyle Tk_GetAnchor Tk_GetJustifyTk_NameOfJustifyTk_NameOfAnchorTk_GetJoinStyleTk_NameOfJoinStyleTk_GetCapStyleTk_GetScreenMM Tk_GetPixelsnumMainWindowscommandscolormapvisual defChangesdefAttsCreateTopLevelWindow NameWindow AllocWindowL$0029L$0364L$0317L$0116L$0140DeleteWindowsExitProcL$0155L$0166L$0181L$0187L$0193L$0199L$0205L$0225L$0229L$0342L$0233L$0237L$0241L$0245L$C0030L$C0031L$C0032L$C0033L$C0034restL$C0035L$C0036L$C0037L$C0038L$C0039L$C0040L$C0041L$C0042L$C0043L$C0044L$C0045L$C0046L$C0047L$C0048 GetScreenL$0031L$0389L$0139L$0146L$0165L$0171L$0183L$0189L$C0024L$0195L$0201L$C0025L$0207L$0226L$0354L$C0026L$0230L$C0027L$0234L$C0028L$0238L$0242L$C0029L$0246L$0330DoConfigureNotify UnlinkWindowOpenIMtkMainWindowList tkDisplayList tkNormalUidtkBitmapImageTypetkPhotoImageType tkActiveUid tkImgFmtGIF tkDisabledUid tkImgFmtPPM TkDeadAppCmdTk_HandleEventXConfigureWindowTk_CreatePhotoImageFormatTcl_ResetResultstrrchrTk_CreateImageTypeTkWmAddToColormapWindowsXFreeTk_RadiobuttonCmd Tk_ScaleCmdTk_ScrollbarCmd Tk_TextCmdTk_ToplevelCmd Tk_TkwaitCmdTk_TkCmdTk_SelectionCmd Tk_RaiseCmd Tk_PlaceCmd Tk_PackCmd Tk_OptionCmdTcl_CreateExitHandler Tk_LowerCmd TkWmNewWindow Tk_ImageCmd Tk_GridCmdTkGetDefaultScreenName Tk_GrabCmdstrtoul XOpenDisplay Tk_FocusCmd TkInitXId Tk_DestroyCmdTk_ClipboardCmdTk_BindtagsCmd Tk_BindCmdTk_CreateBindingTable Tk_BellCmd Tcl_LinkVar Tk_SetAppNameTcl_PkgProvideTcl_PkgRequire XSynchronize Tk_UpdateCmdTk_NameToWindowTkFocusDeadWindow TkCreateFrameTkWmDeadWindowTkWmRemoveFromColormapWindowsXDestroyWindowTkFreeWindowId Tk_WinfoCmdTkEventDeadWindow XDestroyICTkFreeBindingTagsTkOptionDeadWindowTkSelDeadWindowTkGrabDeadWindowTk_DeleteAllBindingsTcl_InterpDeleted Tcl_UnlinkVarTcl_DeleteHashTableTk_DeleteBindingTableTkDeleteAllImagesTk_WmCmdtoupper TkWmMapWindow XMapWindowTcl_DStringAppend XRootWindow TkMakeWindow Tk_ButtonCmd Tk_CanvasCmdTkWmUnmapWindow XUnmapWindow Tcl_GetVarTk_CheckbuttonCmd XMoveWindow Tcl_Merge Tk_EntryCmd XResizeWindowXMoveResizeWindow Tk_FrameCmdXSetWindowBorderWidth Tcl_SplitListXChangeWindowAttributes Tcl_GetVar2 Tk_LabelCmdXSetWindowBackgroundXSetWindowBackgroundPixmap Tk_ListboxCmdXSetWindowBorder Tk_MenuCmdXSetWindowBorderPixmap XGetIMValuesTk_MenubuttonCmd XDefineCursorXOpenIMXSetWindowColormap Tk_MessageCmd TkWmSetClassTkOptionClassChangedTkWmRestackToplevel Tk_IdToWindowTk_RestackWindow Tk_SetClassTk_SetWindowVisualTk_SetWindowColormapTk_StrictMotifTk_UndefineCursorTk_DefineCursorTk_SetWindowBorderPixmapTk_SetWindowBorderTk_SetWindowBackgroundPixmapTk_SetWindowBackgroundTk_ChangeWindowAttributesTk_SetWindowBorderWidthTk_MoveResizeWindowTk_DisplayNameTk_ResizeWindow Tk_MoveWindowTk_ConfigureWindowTk_UnmapWindow Tk_MapWindowTk_MakeWindowExistTk_CreateWindowFromPathTk_CreateWindowTkCreateMainWindowTk_DestroyWindow TkGetDisplayinitialized___7 dontBlock___2DisplaySetupProcL$0017DisplayCheckProcL$0026XQLengthXFlush Tcl_WatchFile Tcl_FileReady XEventsQueuedTk_QueueWindowEvent XNextEventTcl_SetMaxBlockTimeXNoOpTcl_CreateEventSourcemodTable eventTable eventArraymodArray flagArray FindSequenceL$0052L$0086L$0114L$0059GetField MatchPatternsFreeScreenInfoL$0163L$C0049L$C0050L$C0051L$C0052L$C0053L$C0054L$0060L$0061L$0104L$0122 GetKeySymL$0184 ChangeScreenExpandPercentsInitKeymapInfo__ctype2XKeycodeToKeysymTcl_DStringSetLength$$divITkKeysymToStringTk_GetVRootGeometryTcl_BackgroundErrorTkStringToKeysymTcl_FirstHashEntryTcl_NextHashEntryXKeysymToStringXStringToKeysymXFreeModifiermapXGetModifierMappingTcl_AppendElementTcl_ConvertElementTcl_ScanElementTcl_DStringGetResultTcl_GetAssocDataTcl_SetAssocDataTcl_AllowExceptionsTcl_DStringResult XLookupStringXmbLookupString Tk_BindEventTk_CreateBindingTkCopyAndGlobalEvalTk_GetAllBindings Tk_GetBindingTk_DeleteBindingL$0095ClipboardLostSelL$0040ClipboardWindowHandlerClipboardAppHandlerClipboardHandlerL$0101L$0102L$0103L$0105L$0056L$0106L$0107L$0108Tk_GetAtomNameTk_CreateSelHandlerTk_ClipboardClearTk_OwnSelection Tk_InternAtomTk_DeleteSelHandler TkSelInit TkClipInitTk_ClipboardAppend allUid___6 GetDisplayOf GetToplevelWaitVisibilityProcL$0151WaitVariableProcL$0486L$0019L$0489WaitWindowProcL$0088L$0023L$0582L$0583L$0584L$0585L$0586L$0587L$0588L$0173L$0174L$0589L$0590L$0027L$0594L$0593L$0592L$0591L$0562L$0563L$0564L$0565L$0566L$0567L$0568L$0569L$0570L$0571L$0572L$0573L$0574L$0575L$0576L$0577L$0578L$0579L$0580L$0581TkGetPointerCoords Tcl_GetIntTk_GetRootCoordsTk_CreateEventHandler Tcl_TraceVarTcl_UntraceVarTk_DeleteEventHandlerXSyncTkCmapStressedTcl_PrintDoubleTkGetInterpNamesTk_CoordsToWindow Tk_GetColor Tk_FreeColorTkGetServerInfoXVisualIDFromVisualXGetVisualInfoXForceScreenSaverXBellTkBindEventProc pendingPtr genericListlastGenericPtr restrictProcgenericHandlersActive restrictArgDelayedMotionProcL$0083 eventMasksL$0041L$0161L$0194WindowEventProcL$0197L$0175Tcl_QueueEventTkPointerEvent XCreateICTkSelEventProc XFilterEventXRefreshKeyboardMapping TkSelPropProcTcl_CancelIdleCall Tcl_PreserveTcl_DoWhenIdleTkFocusFilterEvent Tcl_Release TkGetFocusTkWmProtocolEventProc TkCurrentTimeTk_RestrictEventsTk_DeleteGenericHandlerTk_CreateGenericHandlerTkQueueEventForAllChildren Tk_MainLoop focusDebug FocusMapProcL$0068L$0127L$0110L$0045L$0046L$0084L$0085L$0120L$0144GenerateFocusEvents ChangeXFocusSetFocus TkGrabState XGrabServerXGetInputFocusTk_CreateErrorHandlerXSetInputFocus XUngrabServerTk_DeleteErrorHandler TkInOutEvents buttonStatesL$0007L$0072GrabWinEventProcL$0093GrabRestrictProcL$0082L$0280L$0057L$0058FindCommonAncestorL$0287L$0113L$0100 MovePointer2ReleaseButtonGrab EatGrabEventsQueueGrabWindowChangeXUngrabPointerTk_Grab XGrabKeyboardXUngrabKeyboard XQueryPointer XGrabPointerTkPositionInTreeTkChangeEventWindow Tk_Ungrab ArrangeGridgridBagHashTable GetGridBagL$0039L$0518L$0192 gridMgrTypeConfigureSlavesGridBagStructureProcL$0478L$0417DestroyGridBagL$0552L$0673L$0223L$0228L$0231L$0222L$0695StringToStickyL$0492L$0694L$0493GridLostSlaveProcL$0227L$0542 GridReqProcL$0224L$0541L$0540Unlink GetMinSizeGetCachedLayoutInfoStickyToString GetLayoutInfoAdjustForGravityTk_ManageGeometryTk_UnmaintainGeometry Tcl_GetDoubleTk_GeometryRequestTcl_GetBooleanTcl_EventuallyFreecurLevelstackslevels cachedWindow numLevels defaultMatchsearchOrder___22serial ExtendArrayNewArray ParsePriorityReadOptionFile AddFromStringGetDefaultOptionsClearOptionTree SetupStacks ExtendStacks OptionInit Tcl_CloseTcl_SeekTcl_OpenFileChannel Tk_GetOptionTcl_ReadXGetWindowPropertyArrangePackingpackerHashTable GetPacker packerTypeL$0335L$0081 sideNames___2L$0176L$0303PackStructureProcL$0135L$0482 DestroyPackerL$0112PackLostSlaveProc PackReqProcL$0501L$0200 YExpansion XExpansionL$0360L$0202L$0109 PackAfterL$0111L$0316L$0358L$0359Tk_MaintainGeometry slaveTable masterTableRecomputePlacementSlaveStructureProcL$0009 placerTypeConfigureSlaveMasterStructureProc FindSlave FindMasterL$0154L$0156L$0053L$0054L$0073PlaceLostSlaveProcPlaceRequestProcL$0055L$0264L$0167L$0263L$0236 UnlinkSlaveL$0214HandleTclCommand LostSelectionL$0220L$0090 SelGetProcL$0315L$0307L$0232L$0235L$0239L$0240XSetSelectionOwnerTkSelGetSelectionTkSelDefaultSelectionTk_GetSelectionTk_ClearSelectionTkSelClearSelectionregistrypendingCommands sendDebug TimeoutProc ValidateNameRegOpenSendInit DeleteProcL$0070AppendErrorProcL$0198 RegFindNameL$0185 SendEventProcSendRestrictProcL$0351 ServerSecureL$0064L$0118L$0196L$0119AppendPropCarefullyRegClose RegAddNameUpdateCommWindow RegDeleteName tkSendSerialXChangeProperty Tk_SendCmdmemmove Tcl_SetResultTcl_CreateModalTimeoutTcl_DeleteModalTimeoutTcl_DStringAppendElement XListHostsXDeletePropertyXGetWindowAttributesWindowIdCleanupCheckRestrictProcAllocXIdWindowIdCleanup2 XCreatePixmap Tk_GetPixmap Tk_FreePixmap wmTracingL$0340 firstWmPtrUpdateGeometryInfoL$0536WaitTimeoutProcL$0375 wmMgrTypeL$0341 WaitForEventL$0506ComputeReparentGeometryTopLevelEventProcL$0002L$0301L$0832L$0748L$0735WaitRestrictProcL$0274L$0599L$0042L$0551L$0018L$0550L$0449L$0450L$0522L$0451L$0426L$0427L$0428L$0429L$0430L$0431L$0432L$0433L$0434L$0435 ParseGeometryL$0452L$0437L$0436L$0448L$0447L$0607L$0446L$0445TopLevelReqProcL$0444L$0443L$0442L$0441L$0747L$0440L$0439L$0796L$0438L$0844WaitForConfigureNotify ReparentEventConfigureEvent GetMaxSizeUpdateVRootGeometry UpdateHintsUpdateWmProtocolsWaitForMapNotifyUpdateSizeHintsXStringListToTextPropertyXSetWMColormapWindowsXGetWMColormapWindowsXTranslateCoordinates XGetGeometry XQueryTreeXSetTransientForHint XSetIconName XSetWMName XSelectInputXWithdrawWindowXSetWMClientMachine XSetCommandXAllocClassHintXIconifyWindow XSetClassHint XCreateWindowXAllocSizeHintsXSetWMNormalHints XSetWMHintsXReconfigureWMWindow Tk_UnsetGridTk_MoveToplevelWindow Tk_SetGrid configFlags DisplayButton configSpecsButtonTextVarProc ButtonVarProcL$0016 optionStrings classNames ButtonCreateL$C0066L$C0077L$C0105L$C0072L$C0083L$C0082L$C0080L$C0079L$C0087L$C0076L$C0075L$C0088L$C0059L$C0058L$C0057L$C0097L$C0098L$0010ButtonCmdDeletedProcButtonWidgetCmdL$C0099ButtonEventProcL$C0084L$0380ConfigureButtonL$C0112L$C0113L$0147ButtonImageProcButtonSelectImageProcL$0170L$0302L$0327L$0355L$0363L$C0102L$C0103L$C0104L$C0106L$C0107L$C0108L$C0109L$C0110L$C0111L$C0114L$C0115L$C0116L$C0117L$C0118L$C0119L$C0120L$C0123L$C0124L$0383L$0011L$C0055L$C0056L$C0060L$C0061L$C0062L$C0063L$C0064L$C0065L$0076L$C0122L$0077 InvokeButtonL$0078L$C0067L$C0068L$C0069L$C0070L$C0071L$C0073L$C0074L$C0078L$C0121L$C0081L$C0085L$C0086L$C0089L$C0090L$C0091L$C0092L$C0093L$0297L$0298L$C0094L$0299L$0300L$C0095L$C0096L$0321L$0344L$C0100L$0374L$C0101ComputeButtonGeometry DestroyButton Tk_FreeGCTk_3DBorderColor Tk_FreeImageTk_GetGCTk_SetBackgroundFromBorder Tk_GetImageTk_Fill3DRectangleTk_SizeOfImageXSetClipOriginTk_Draw3DRectangle Tk_3DBorderGCXFillRectangleXSetForeground XTextWidthTk_ConfigureValueTk_ConfigureInfo Tcl_SleepTk_FreeOptionsTk_ConfigureWidgetTk_RedrawImage XCopyPlane TkDisplayText XFillPolygonTk_Fill3DPolygonTk_Draw3DPolygon Tk_GCForColorTk_DrawFocusHighlight XCopyAreaTcl_DeleteCommandTcl_GetCommandNameTkComputeTextGeometryTk_SetInternalBorderL$0065 GetEntryIndexEntryTextVarProcEntryLostSelectionEntryBlinkProc DisplayEntryL$0296ConfigureEntryEntryFetchSelectionEntryEventProcEntryWidgetCmdEntryCmdDeletedProcL$0402L$0285 DestroyEntryL$0143L$0145L$0406L$0148L$0149L$0150L$0152L$0153L$0157L$0158L$0159L$0160L$0162L$0164L$0168L$0169L$0311L$0310L$0286EntryFocusProc EntrySetValueEntryValueChangedEventuallyRedrawEntryComputeGeometryEntryVisibleRangeEntryUpdateScrollbar EntrySelectTo EntryScanTo InsertChars DeleteCharsTkMeasureCharsTkDisplayCharsTk_GetScrollInfo DisplayFrameMapFrame DestroyFrameConfigureFrameFrameEventProcFrameWidgetCmdFrameCmdDeletedProcL$0043L$0050L$0051L$0121Tk_GetColormap Tk_GetVisualTk_FreeColormapGetListboxIndexDisplayListboxListboxLostSelectionNearestListboxElementListboxEventProcListboxWidgetCmdListboxCmdDeletedProcConfigureListboxDestroyListboxListboxFetchSelectionL$0369L$0385L$0206L$0208L$0209L$0210L$0211L$0212L$0213L$0215L$0216L$0217L$0218L$0219L$0221L$0388ListboxUpdateVScrollbarListboxComputeGeometryChangeListboxOffset ListboxSelectChangeListboxViewListboxUpdateHScrollbar ListboxScanTo InsertEls DeleteElsListboxRedrawRangeTk_3DVerticalBevelTk_3DHorizontalBevel XTextExtents XDrawStringentryConfigSpecsComputeMenuGeometry GetMenuIndex MenuVarProc DisplayMenuActivateMenuEntry PostSubmenuDestroyMenuEntryL$0403ConfigureMenuEntryL$0483L$0418L$0411L$0371L$0357L$0350MenuSelectImageProc MenuImageProcMenuCmdDeletedProc MenuWidgetCmd MenuEventProc ConfigureMenu MenuNewEntryL$0253 DestroyMenuL$0203L$0204MenuAddOrInsertL$0268L$0332L$0191L$0190L$0376L$0377L$0188L$0186L$0558EventuallyRedrawMenuTkUnderlineChars XRaiseWindowTcl_StringMatchDisplayMenuButtonMenuButtonTextVarProcL$0012MenuButtonCmdDeletedProcMenuButtonWidgetCmdMenuButtonEventProcConfigureMenuButtonL$0021DestroyMenuButtonL$0074MenuButtonImageProcL$0092L$0025ComputeMenuButtonGeometryDisplayMessageMessageTextVarProcMessageCmdDeletedProcMessageWidgetCmdMessageEventProcConfigureMessageDestroyMessageL$0035L$0024L$0044ComputeMessageGeometryRoundToResolution ScaleVarProc ValueToPixel DisplayScale DestroyScaleScaleCmdDeletedProcScaleWidgetCmdScaleEventProcConfigureScaleL$0254L$0063L$0066L$0067 PixelToValueL$0069 ScaleElementL$0071L$0258L$0257DisplayHorizontalScaleDisplayVerticalValueDisplayVerticalScaleEventuallyRedrawScaleDisplayHorizontalValueComputeScaleGeometry ComputeFormat SetScaleValuefloorlog10L$0020DisplayScrollbarScrollbarCmdDeletedProcScrollbarWidgetCmdScrollbarEventProcConfigureScrollbarDestroyScrollbarL$0132L$0133L$0134L$0136L$0137L$0138L$0141ScrollbarPositionL$0142ComputeScrollbarGeometrytypeListStartTagSearchNextItemallUid currentUidnumSlowSearches DisplayCanvas numIdSearchesL$0559CanvasBlinkProcCanvasBindProcCanvasEventProcCanvasWidgetCmdCanvasCmdDeletedProcL$0889L$0750CanvasLostSelection DestroyCanvasL$0812ConfigureCanvasCanvasFetchSelectionL$0667L$0744 GridAlignL$0453L$0454L$0455L$0456L$0457L$0458 FindItemsL$0459L$0460L$0461L$0462L$0463L$0464L$0465L$0466L$0467L$0468L$0469L$0897L$0470L$0471L$0472L$0473L$0474L$0475L$0476L$0477L$0479L$0480L$0481L$0484L$0485L$0487L$0488L$0490L$0491L$0494CanvasFindClosestL$0822L$0766L$0678FindAreaL$0765DoItemCanvasUpdateScrollbarsPickCurrentItemCanvasFocusProcPrintScrollFractions CanvasDoEventCanvasSelectToCanvasSetOrigin InitCanvas RelinkItemsTk_CanvasGetCoord tkOvalType tkWindowType tkArcType tkBitmapTypetkRectangleType tkTextType tkLineType tkPolygonType tkImageTypeTkCanvPostscriptCmdTk_GetItemTypesTk_CreateItemTypeTk_CanvasEventuallyRedraw imageTypeListid___4L$0032L$0091 DeleteImageTcl_GetCommandInfoTk_NameOfImageTk_DeleteImageTk_ImageChangedNextBitmapWordImgBmapConfigureMaster ImgBmapCmdImgBmapCmdDeletedProcL$0089 ImgBmapFreeImgBmapDisplay ImgBmapGet ImgBmapCreateL$0115L$0180 ImgBmapDeleteL$0182ImgBmapConfigureInstanceTkGetBitmapData__filbufTcl_PosixErrorsp___28clear_code___24 curbit___32buf___10 oldcode___23code_size___18firstcode___22 table___26 max_code___20 stack___27 lastbit___33 done___34max_code_size___21 fresh___17last_byte___35buf___31 ZeroDataBlockset_code_size___19 end_code___25 GetDataBlockL$0034GetCode ReadGIFHeader LWZReadByte ReadColorMap DoExtension ReadImage FileReadGIF FileMatchGIFTk_PhotoPutBlockTk_PhotoExpandReadPPMFileHeader FileMatchPPM FileWritePPM FileReadPPM__flsbuffseekimgPhotoColorHash formatList imgPhotoHashimgPhotoHashInitialized optionNames CountBitsimgPhotoColorHashInitializedDisposeInstancepaletteChoice___14ParseSubcommandOptionsDisposeColorTableL$0062L$0347L$0404ImgPhotoCmdDeletedProc ImgPhotoCmdImgPhotoConfigureMasterMatchFileFormatL$0705L$0658L$0680L$0272MatchStringFormatIsValidPaletteL$0370ImgPhotoDelete ImgPhotoFreeImgPhotoDisplay ImgPhotoGetImgPhotoCreate ReclaimColorsL$0662L$0704L$0761ImgPhotoConfigureInstanceFreeColorTable GetColorTableAllocateColorsImgPhotoInstanceSetSizeDitherInstanceDitherImgPhotoSetSizepowXClipBox XCreateRegionXDestroyRegionXUnionRectWithRegion XFreeColors strncasecmpTk_PhotoGetImageTk_PreserveColormap XAllocColor XCreateImage_XInitImageFuncPtrs Tk_FindPhoto XSetRegion XParseColor XSetClipMaskXIntersectRegion XPutImageTk_PhotoPutZoomedBlock Tk_PhotoBlankTk_PhotoGetSizeTk_PhotoSetSize TextBlinkProc TextEventProcTextFetchSelection ConfigureText DestroyTextL$0289L$0395TextCmdDeletedProcL$0515 DumpSegmentL$0521 TextWidgetCmdL$0008 TextDumpCmd TextSearchCmdL$0534L$0535DumpLinetkTextNormalUidtkTextCharType tkTextCharUidTkTextGetIndex tkBTreeDebugTkTextMakeIndexTkTextIndexForwChars tkTextNoneUidtkTextDisabledUid tkTextWordUidTkTextIndexCmpTkBTreeNumLinesTkBTreeLineIndex tkTextDebugtkTextToggleOnType TkBTreeTagtkTextToggleOffTypeTkBTreeNextTag TkTextChangedTkTextSetYView TkTextSetMarkTkTextIndexToSegTkTextPrintIndexTkBTreeGetTagsTkTextCreateTagTkTextRedrawTagTkBTreeStartSearchTkBTreeCharTaggedTkTextLostSelectionTkTextRelayoutWindowTkTextMarkSegToIndexTkTextIndexBackCharsTkTextBindProctolowerTkBTreeFindLine TkBTreeCreateTkTextCreateDInfoTkTextCharBboxTkTextDLineInfo TkTextMarkCmd TkTextScanCmd TkTextSeeCmd TkTextTagCmdTkTextWindowCmdTkTextXviewCmdTkTextYviewCmdTkTextFreeDInfoTkBTreeDestroy TkTextFreeTag TkTextGetTabsTkTextRedrawRegionTkBTreeInsertCharsTkBTreeDeleteCharsTkBTreeCharsInLineTcl_RegExpCompileTcl_RegExpExecTcl_RegExpRangeTkBTreeNextLineshiftTable___32 borderTable IntersectL$0131 GetShadows ShiftLine BorderInitTk_GetColorByValuecosatanTk_NameOfReliefTk_Get3DBorderTk_Free3DBorderTk_NameOf3DBorder Tk_GetRelief atomNameArrayAtomInit XInternAtom XGetAtomName valueTable string___6L$0022DeleteStressedCmap ColorInitFindClosestColor XLookupColorXAllocNamedColor XQueryColors XCreateGCXFreeGCTk_NameOfColorL$0338FindConfigSpecDoConfigFormatConfigInfoFormatConfigValueL$0304L$0305L$0306L$0308L$0309L$0353L$0352Tk_FreeFontStruct Tk_FreeCursor Tk_GetCursorTk_GetFontStructTk_NameOfFontStructTk_NameOfCursordefaultHandler ErrorProcXSetErrorHandler fontTablelastFontStructPtr lastFontPtrhexCharsmapChars string___4FontInitSetFontMetricsXGetFontPropertyXLoadQueryFont XFreeFontGCInitXGContextFromGCmaintainHashTableMaintainMasterProcMaintainCheckProcMaintainSlaveProcL$0080XFillRectangles visualNamesL$0124XCreateColormap XFreeColormap pendingIncrspendingRetrievalsSelRcvIncrProcSelTimeoutProcIncrTimeoutProc SelCvtFromX SelCvtToX SelectionSizeConvertSelection XSendEventXConvertSelection pieSliceUidchordUidarcUid AngleInRange VertLineToArcHorizLineToArc ConfigureArc ArcToPointL$0130L$0129L$0128 CreateArc ArcCoords DeleteArc DisplayArc ArcToAreaArcToPostscriptScaleArc TranslateArcL$0094 tagsOptionComputeArcOutlineComputeArcBboxsinTkIncludePointTk_CanvasDrawableCoordsTk_CanvasPsStippleTk_CanvasPsColorTkPolygonToPointatan2Tk_CanvasTkwin TkLineToPointTkGetButtPoints TkLineToAreaTkPolygonToArea Tk_CanvasPsY TkFillPolygon TkOvalToPointhypot XDrawLinesqrt XSetTSOriginTk_CanvasSetStippleOriginTk_CanvasPsPathXFillArcXDrawArcTk_CanvasTagsPrintProcTk_CanvasTagsParseProcConfigureBitmap CreateBitmap BitmapCoords DeleteBitmap DisplayBitmap BitmapToPoint BitmapToAreaBitmapToPostscript ScaleBitmapTranslateBitmapComputeBitmapBboxTk_CanvasPsBitmapConfigureImageImageChangedProc ImageCoords DisplayImage ImageToPoint ImageToArea ScaleImageTranslateImage CreateImageComputeImageBboxnoneUidfirstUidlastUidbothUidL$0256ConfigureArrows ConfigureLineArrowheadPostscript LineCoordsL$0015 CreateLine DeleteLine DisplayLine LineToPoint LineToAreaLineToPostscript ScaleLine TranslateLinePrintArrowShapeL$0284L$0283arrowShapeOptionParseArrowShapeComputeLineBboxTkMakeBezierCurveTkGetMiterPoints XDrawLinesTkThickPolyLineToAreaTkMakeBezierPostscript PolygonCoordsConfigurePolygonPolygonToPostscript ScalePolygonTranslatePolygon CreatePolygon DeletePolygonDisplayPolygonPolygonToPoint PolygonToAreaComputePolygonBboxL$0003GetPostscriptPointsL$0075fputsendpwentctimefgets XGetImageTk_CanvasPsFont TextToAreaTextToPostscript ScaleText TranslateText GetTextIndex SetTextCursor GetSelText TextInsertTextDeleteChars CreateText TextCoords DeleteText DisplayText TextToPointComputeTextBboxTk_CanvasGetTextInfoTk_CanvasWindowCoordsWinItemStructureProccanvasGeomTypeConfigureWinItem CreateWinItem WinItemCoords DeleteWinItemDisplayWinItemWinItemToPoint WinItemToArea ScaleWinItemTranslateWinItemWinItemRequestProcWinItemLostSlaveProcComputeWindowBboxConfigureRectOvalCreateRectOvalRectOvalCoordsDeleteRectOvalDisplayRectOvalRectOvalToPostscript ScaleRectOvalTranslateRectOval RectToPoint RectToArea OvalToPoint OvalToAreaComputeRectOvalBbox TkOvalToAreaXDrawRectangleSplitSegL$0866L$0282ToggleCheckProcL$0672ToggleLineChangeProcToggleCleanupProcToggleDeleteProcL$0668L$0251L$0842L$0710 CharCheckProcCharCleanupProcCharDeleteProc FindTagEndL$0741 FindTagStartL$0742L$0325L$0743L$0277L$0915 CharSplitProcL$0916L$0917IncCountCheckNodeConsistencyDeleteSummariesChangeNodeToggleCount CleanupLineRecomputeNodeCounts Rebalance DestroyNodetkTextLeftMarkTypetkTextRightMarkTypeTkTextCharLayoutProcTkBTreeStartSearchBackTkBTreePrevTagTkBTreeLinkSegmentTkBTreeUnlinkSegment TkBTreeCheckTkBTreePreviousLine FindDLine linesRedrawn LayoutDLine numCopies numRedisplaysL$0617CharDisplayProcL$0339L$0549L$0637L$0825L$0682CharUndisplayProcCharMeasureProc CharBboxProc SizeOfTabL$0125GetStyleL$0606L$0420L$0648L$0649L$0650L$0651L$0876L$0681L$0696L$0126DisplayLineBackground DisplayDLine ScrollByLinesUpdateDisplayInfo AdjustForTabGetXViewTextInvalidateRegion FreeStyleGetYView MeasureUp FreeDLinesTkTextInsertDisplayProcTkTextPickCurrentTkScrollWindow XRectInRegionTkTextPixelIndexTkTextEventuallyRepickL$0047StartEndForwBack__alnumTkTextMarkNameToIndexTkTextWindowIndexTkTextSegToOffsetMarkLayoutProcMarkCleanupProcMarkDeleteProc MarkCheckProcInsertUndisplayProc MarkFindPrev MarkFindNexttagConfigSpecsFindTagL$0178L$0292 TagSortProcL$0334SortTagsChangeTagPriorityqsorttkTextEmbWindowTypeEmbWinStructureProc textGeomTypeEmbWinDelayedUnmapL$0033EmbWinDisplayProcEmbWinBboxProcEmbWinUndisplayProcL$0096EmbWinConfigureL$0048L$0038AlignPrintProcAlignParseProc alignOptionEmbWinCheckProcEmbWinLayoutProcEmbWinCleanupProcEmbWinDeleteProcEmbWinLostSlaveProcEmbWinRequestProc CursorInitTkCreateCursorFromData TkFreeCursorTkGetCursorByNameTk_GetCursorFromDataScrollRestrictProc XEmptyRegionelevenDegrees___26L$0259L$0267TkBezierScreenPointsTkBezierPoints cursorNamesXCreatePixmapCursor XFreeCursor XLoadFontXCreateGlyphCursor panicProcabortTcl_SetPanicProcassocDataCounter___4 builtInCmdsDeleteInterpProcL$0030L$0252L$0250 tclTypeTableTcl_RegisterChannelTcl_GetStdChannelTclPrecTraceProcTclExpandParseValueTcl_AsyncReadyTcl_AsyncInvoke Tcl_GlobalCmdTcl_HistoryCmd Tcl_IfCmd Tcl_IncrCmd Tcl_InfoCmd Tcl_InterpCmd Tcl_JoinCmdTcl_LappendCmd Tcl_LindexCmdTcl_LinsertCmd Tcl_ListCmdTcl_LlengthCmd Tcl_LoadCmd Tcl_LrangeCmdTcl_LreplaceCmdTcl_LsearchCmd Tcl_LsortCmdTcl_PackageCmd Tcl_ProcCmd Tcl_RandomCmd Tcl_RegexpCmd Tcl_RegsubCmd Tcl_RenameCmd Tcl_ReturnCmd Tcl_ScanCmd Tcl_SetCmd Tcl_SplitCmd Tcl_StringCmd Tcl_SubstCmd Tcl_SwitchCmd Tcl_TraceCmd Tcl_UnsetCmdTcl_UplevelCmd Tcl_UpvarCmd Tcl_WhileCmd Tcl_AfterCmd Tcl_CdCmd Tcl_CloseCmd Tcl_EofCmd Tcl_AppendCmdTcl_FblockedCmdTcl_FconfigureCmd Tcl_FileCmd Tcl_FlushCmd Tcl_GetsCmd Tcl_GlobCmd Tcl_OpenCmd Tcl_PidCmd Tcl_PutsCmd Tcl_PwdCmd Tcl_ReadCmd Tcl_SeekCmd Tcl_SocketCmd Tcl_TellCmd Tcl_TimeCmd Tcl_UpdateCmd Tcl_VwaitCmdTclUnsupported0Cmd Tcl_ExecCmd Tcl_SourceCmd Tcl_ArrayCmd TclSetupEnv TclInterpInitTclPlatformInit Tcl_TraceVar2 Tcl_BreakCmd Tcl_CaseCmd Tcl_CatchCmd Tcl_ClockCmd Tcl_ConcatCmdTcl_ContinueCmd Tcl_ErrorCmd Tcl_EvalCmd TclDeleteVarsTclFreePackageInfo Tcl_ExitCmd Tcl_ExprCmdTcl_FileEventCmd Tcl_ForCmdTcl_SetErrorCode Tcl_Backslash TclParseWordsTcl_ForeachCmdTclUpdateReturnInfo Tcl_FormatCmdTcl_SetCommandInfoTcl_CreateTraceTcl_DeleteTraceTcl_DeleteAssocDataTcl_DontCallWhenDeletedTcl_CallWhenDeletedTcl_SetRecursionLimitfirstModalHandlerPtrfirstFileHandlerPtrfirstTimerHandlerPtridleList firstExitPtr lastIdlePtr nextId___51timerEventSourceCreatedidleGeneration AfterProcid___14TimerHandlerSetupProcfileEventSourceCreatedTimerHandlerCheckProcFileHandlerSetupProcTimerHandlerExitProcFileHandlerCheckProc VwaitVarProcHandleBgErrorsBgErrorDeleteProcTimerHandlerEventProcFileHandlerEventProcFileHandlerExitProcAfterCleanupProc GetAfterEventL$0265L$0262L$0261L$0260 FreeAfterPtr Tcl_Write TclGetTime Tcl_ConcatTcl_DeleteEventSource Tcl_FlushTcl_WaitForEventTclServiceIdleTclIdlePendingTcl_DeleteExitHandlerTcl_ExittclMemDumpFileNameTclWaitForFile fileTable FileExitProcTcl_SetNotifierDataTcl_GetNotifierDataTcl_GetFileInfo Tcl_FreeFilemacRootPatternPtrwinRootPatternPtrFileNameCleanupL$0497 SplitMacPathExtractWinRoot SkipToChar DoTildeSubst SplitWinPath SplitUnixPathL$0520L$0382 tclPlatform TclRegExec TclRegComp Tcl_JoinPathaccess TclDoGlobstrpbrkTclGetUserHome TclGetEnv TclMatchFilesTclGetExtension Tcl_SplitPathTcl_GetPathTypeTclExprFloatError HashString BogusFind OneWordFind ArrayFind StringCreate StringFind BogusCreate ArrayCreate OneWordCreate RebuildTable Tcl_HashStats firstChanPtrnestedHandlerPtrL$1045 stderrChannel stdoutChannel stdinChannelChannelEventScriptInvokerstdinInitializedchannelEventSourceCreatedstdoutInitializedstderrInitialized optionValchannelExitHandlerCreated FlushChannelChannelHandlerSetupProcChannelHandlerCheckProcChannelHandlerEventProcL$0928L$0963L$0278CloseChannelsOnExitL$1128L$1059L$0893GetInputL$0318L$0794CopyAndTranslateBufferFlushEventProcChannelEventSourceExitProcL$0769ChannelEventDeleteProcDeleteChannelTableGetChannelTableL$1075L$0337L$0901L$1074L$1073 CloseChannelL$1072L$0930L$0931L$0291L$1071L$1070L$1069L$1068L$1066GetEOLL$0786ScanInputForEOLL$1067L$1134ScanBufferForEOLL$0805 RecycleBufferDiscardOutputQueuedDiscardInputQueuedCreateScriptRecordDeleteScriptRecordReturnScriptRecord Tcl_SetErrnoTcl_GetChannelTclGetDefaultStdChannelTcl_DStringEndSublistTcl_DStringStartSublistTcl_SetChannelOptionTcl_TellTcl_InputBufferedTcl_DeleteEvents Tcl_IsSafeTcl_GetChannelTypeTcl_GetChannelFileTcl_GetChannelInstanceDataTcl_CreateChannelTcl_UnregisterChannelTcl_EofTcl_InputBlockedTcl_SetChannelBufferSizeTcl_GetChannelBufferSizeTcl_GetsTcl_GetChannelOptionTcl_GetChannelNameTcl_DeleteChannelHandlerTcl_SetStdChannelTcl_CreateCloseHandlerTclTestChannelCmdTcl_DeleteCloseHandlerTclTestChannelEventCmdTcl_CreateChannelHandlerdetListFileForRedirect TclCloseFileTclClosePipeFile Tcl_WaitPid Tcl_SignalMsg Tcl_SignalId TclSeekFileTclCreateTempFile TclCreatePipe TclOpenFiletmpnamTclSpawnPipelineTclCreatePipeline Tcl_ErrnoMsg Tcl_ErrnoIdTclCreateCommandChannelTclCleanupChildren Tcl_GetErrnoTcl_DetachPids Tcl_EvalFileTcl_OpenCommandChannelTclGetOpenModeTcl_ReapDetachedProcs LinkTraceProc StringValueL$0049Tcl_VarTraceInfoTcl_UpdateLinkedVar firstEventPtr lastEventPtrmarkerEventPtr blockTime blockTimeSet ServiceEventtclFirstEventSourcePtr CheckVersionComparePkgVersions FindPackageL$0036L$0005refArrayinUsespaceAvlPreserveExitProcL$0396L$0498L$0408L$0409L$0525SetupAppendBufferTclGetRegError TclNeedSpace TclRegErrorTclFindElementTcl_RegExpMatchTclGetListIndexTclCopyAndCollapse noSuchVar noSuchElementisArray LookupVar CallTraces MakeUpvar danglingUpvar needArray ParseSearchIdL$0373L$0407L$0387L$0366L$0365 CleanupVar VarErrMsgDeleteSearchesNewVar DeleteArray TclGetFrame Tcl_UnsetVar2Tcl_VarTraceInfo2 Tcl_UnsetVar Tcl_UpVar Tcl_UpVar2Tcl_UntraceVar2tcpChannelTypepipeChannelTypefileChannelTypeCommonBlockModeProcWaitForConnectFilePipeInputProc CreateSocketCreateSocketAddressFilePipeOutputProc TcpAcceptL$0087TcpGetOptionProcL$0117 TcpOutputProc TcpInputProc TcpCloseProcTcpBlockModeProc PipeCloseProc FileSeekProc FileCloseProc gethostbyaddrTcl_MakeFileChannelfdopen getpeername getsocknameTclSockMinimumBufferslistenacceptTcl_OpenTcpServerTclGetAndDetachPidsTcl_OpenTcpClientTcl_MakeTcpClientChannelTcl_GetOpenFile readyMasks numFdBits checkMasks delay___10 MaskEmptyregdummyregnodeerrMsgregnextregmatchregregtry regbranchregpieceregatom regrepeatregtailregc regoptail reginsertstrcspn lastHandler firstHandler asyncReady asyncActive Tcl_AsyncMarkTcl_AsyncCreateTcl_AsyncDelete ParseTime FormatClock TclGetSeconds TclGetClicks TclGetDateTclGetTimeZonegmtime localtimestrftimeGetTypeFromModeL$0329L$0610L$0247L$0248L$0249 StoreStatDataL$0372L$0608L$0609lstatTcl_ExprStringgeteuidTcl_ExprBooleanreadlinkTclChdir sortInterpsortCodesortModesortIncreasingsortCmdL$0424L$0533SortCompareProcL$0037L$0328tclExecutableName TclFindProcTcl_GetHostNameTclGetLoadedPackages TclIsProcTcl_CommandComplete TraceVarProcL$0621L$0723L$0519L$0690L$0751L$0732L$0731L$0547L$0598L$0348L$0349L$0652L$0653 TclGetCwdTclPreventAliasLooprand Tcl_ParseVarsrand environSizefirstInterpPtr EnvTraceProc FindVariable EnvExitProcEnvInitenviron Tcl_PutEnv TclSetEnv TclUnsetEnv ExprUnaryFunc precTable ExprGetValueL$0401 funcTableExprLexoperatorStrings ExprTopLevelL$0537ExprBinaryFuncL$0269ExprParseStringExprLooksLikeInt ExprAbsFuncExprDoubleFunc ExprIntFunc ExprRoundFuncL$0548 ExprMathFuncExprMakeStringtcl_MathInProgressacosasinceilcoshexpfmodlogsinhtantanhTclParseQuotesTclParseBracesmatherr Tcl_ExprLongTcl_CreateMathFuncTcl_ExprDouble tclMatherrPtrGetEvent SubsAndEvalGetWords InsertRev InitHistory RevCommand MakeSpaceDoRevs RevResultTcl_RecordAndEval TclWordEnd GetInterpTclCommandsToKeepCt aliasCounterAliasCmdinterpCounter___10L$0273SlaveRecordDeleteProcTclCommandsToKeepL$0324 AliasHelperL$0398MasterRecordDeleteProcL$0275 DescribeAlias CreateSlaveSlaveObjectDeleteProcSlaveObjectCmdAliasCmdDeleteProcMakeSafe DeleteAliasDeleteOneInterpObjectCreateInterpObjectDeleteInterpObjectL$0399SlaveAliasHelper GetTargetL$0288L$0290L$0293L$0294Tcl_GetInterpPathTcl_Init Tcl_MakeSafeTcl_CreateSlave Tcl_GetSlave Tcl_GetMasterTcl_CreateAlias Tcl_GetAliasTcpAcceptCallbacksDeleteProcTcpServerCloseProcAcceptCallbackProc$UnregisterTcpServerInterpCleanupProcRegisterTcpServerInterpCleanupTclSockGetPort getservbynamefirstPackagePtrLoadCleanupProc LoadExitProc TclLoadFileTclGuessPackageNameTcl_StaticPackageQuoteEnd ScriptEnd VarNameEndL$0266TclParseNestedCmd InterpProcProcDeleteProc CleanupProc currentDirexecutableNameExitHandlerSetcurrentDirExitHandlerSetFreeExecutableNameFreeCurrentDirgetcwdchdirunlinkwaitpidgetpwnamopendirreaddirclosedir TclWriteFile TclReadFileTcl_FindExecutable SetupStdFileRestoreSignals_exitdup2vforkpipeexecvpTcl_CreatePipeline setTZ___6timezonetzsetinitialized___2 initScriptdefaultLibraryDiruname TclDateInputTclDateRelSeconds TclDateMonthTclDateMinutes TclDateHour TclDateDayTclDateRelMonthTclDateHaveTimeTclDateSecondsTclDateDSTmodeTclDateTimezoneTclDateHaveDateTclDateHaveDayTclDateMeridianTclDateHaveRel TclDateYearTclDatemaxdepthTclDateDayOrdinal TimezoneTableTclDateDayNumberTclDateHaveZone UnitsTableDaysInMonth___6 MonthDayTable OtherTable MilitaryTableConvert DSTcorrectL$C0125 ToSeconds RelativeDate RelativeMonth LookupWord TclDatelex TclDateerror TclDatelval TclDatecharTclDates TclDateact TclDatevalTclDatevTclDateerrflag TclDatepv TclDatetmp TclDatepgo TclDatechk TclDatestate TclDateps TclDatenerrs TclDater1 TclDatepact TclDateexca TclDatedef TclDater2TclDate_TclDatev TclDateparseTclDate_TclDates TclDatedebughostnameInited shl_findsymshl_loadinitialized___6 __CTOR_LIST__ __DTOR_LIST____do_global_dtors__gcc_plt_callatexit__do_global_ctors_exit_dummy_ref_exit_dummy_decl_iob_environ _sys_nerr _sys_errlist __timezoneLIBC//Mdiv_const.o0HPUX Precision Architecture vers PA2.0 assembler92453A.08.12 (sllic PA1.1)$neg3$pos$neg$neg5$neg6 $pos_for_17$neg10 $neg_for_17$neg12$neg15$neg17$u17$neg7$7$pos7$1$2$8 $neg7_shift$3$4$neg9$neg14$$divide_by_constant$$divI_2$$divI_4$$divI_8 $$divI_16$$divI_3$$divU_3$$divI_5$$divU_5$$divI_6$$divU_6 $$divU_10 $$divI_12 $$divU_12 $$divI_15 $$divU_15 $$divI_17 $$divU_17$$divI_7$$divU_7$$divI_9$$divU_9 $$divI_14 $$divU_14 LIBC//MdivI.o negative1 small_divisornormal$$divoI LIBC//MremI.ot1finish LIBC//MremU.o special_caseLIBC//MdyncallU.onoshlibsetextedataend_etext_edata_end __SYSTEM_ID _fp_statusetextedataend_etext_edata_end@L@LL@Lt@LӜ@LN0p /T`=+ =,~X*=BDLQ( NY. >[W]FU"_<F,:OdHJ@dP@`Z@U\@Ue@Ur@U}@U@U@U@U@U@U@U@U@U@8U@U z U U YU @U  YU @U YU @U PU @U YU @U  @U @U  U @U U! @ U U# @(U Z U% @0U  <U' @8U  U) @@U  U+ @HU & ( Z$U- (@PU 4 .U/ 4@XU D Z<U1 D@`U M ZTU3 M@hU 2 Z ZlU5 Z@pU g ZU7 g@xU s gU9 s@U 0 | U; |@U U= @U  U? @U @ UA @U : UC @U UE @U D (UG @U 0UI @U 8 cHUK @U 4 x8UM @U  UO@U UQ@U "US"@U 2UU2@U = UW=@U UY@U U[@U ,=U]@U NU_@0U T4Ua@8U b@Uc@@U bXUe@HU bpUg@PU [Ui@XU bUk@`U ,bUm,@hU J<bUo<@pU VIbUqI@xU rUbUsU@U acUua@U HmfUwm@U "~cUy~@U Lc0U{@U zcHU}@U LU@U $ DU@U jU@U BU@U RU@U !U@U U@U 6dU@U <U@U hU@U t+ U+@U l78U7@U ZFeHUF@U *RPUR@U X`hU`@ U bpUp@(U U@0U PU@8U U@@U U@HU > U@PU $U@XU \<U@`U nTU@hU lU@pU |U@xU U@U U@U U@U f,U,@U :U:@U xGUG@U TUT@U cUc@U ~pUp@U }dU}@U c`U@U IPU@U IhU@U IU@U IU@U cxU@U IU@U IU@U 8U@U IU@U ^ %PU @ U IU@(U "U"@0U p-JU-@8U 9J(U9@@U EJ@UE@HU SJXUS@PU |_,U_@XU k|Uk@`U yUy@hU JpU@pU JU@xU DU@U _@U u@U z@U @(U @pU @hU @U @U @XU @HU @U (@`U v@xU @@U @ U @U @U @0U @8U @PU  U @U ' U '@ U 0 U 0@(U = 8U=@0U F UF@8U W UW@@U .i Ui@HU { 4U{@PU  $U@XU  <U@`U  TU@hU   lU@pU ` U!@xU  U#@U $ U%@U  U'@U  U)@U & U+@U # U-#@U . ;U/.@U 04 ;U14@U J ;U3J@U 2[ ,U5[@U h DU7h@U 8w \U9w@U 6 tU;@U  U=@U  U?@U  UA@U  UC@U  UE@U @ UG@U  UI@U  4UK@ U & ZUM&@0U *@U 4 D,UP@U J%;lUR%;@U %]UT%]@ U S&,UV&,@U 'DUX'@U '4nUZ'4@U *U\*@U *ۜU^*@U  ' 0 = F W i {           # . 4 J [ h w          & 3DUdu$5AVetz  $0>NWgy   % 3 C Y m | !!!!'!4!A!W!h!y!!!!!!!"""""0"D"P"\"u""""""#####6#E#T#h#w########$ $"$2$B$Q$f$t$$$$$$$$% %%-%; %J%] %q%}z %%%%%%%%& & &, &D&T&f&v&&&&&&&&' z '#'4 'H']'r''''''((} ($(.(;(H(X(c(p(z(((((((()))5)M)e))z z ))))))))* *#*6*M*j*}**z ***** *  !)/6;CJQX`gox &.8AHNV_elsz &+27?FMT\dmt{ !,28CMVbglpuz~ -:IYit1;N^k )9FS`o".@Oes}    , 9 D S ] h y          % 2 > Y k u            % 8 D U [ k w            ! 1 9 D W n              ( 4 D M Z g s |         "2=LXjv $0=LXhu #0@MZhv %5EP^it ';HYdr}#4BP_n|(=K]it +:HZn,<IUam~+7FR`p,:GTcp} "-9ES_ky&3@N_g'0=FWi{#.4J[hw&3DUdu$5AVet$0>NWgy   % 3 C Y m | !!!!'!4!A!W!h!y!!!!!!!"""""0"D"P"\"u""""""#####6#E#T#h#w########$ $"$2$B$Q$f$t$$$$$$$$% %%-%;%J%]%q%}%%%%%%%%& & &,&D&T&f&v&&&&&&&&''#'4'H']'r''''''((($(.(;(H(X(c(p(z(((((((()))5)M)e))))))))))* *#*6*M*j*}********     sdr/usr/lib/X11R5/libX11.sl/lib/libm.sl/usr/lib/libdld.sl/lib/libc.slerrno__dld_loc__timezone_sys_errlist_SYSTEM_IDsys_errlist_environ_iob__ctype2__ctypesys_nerr__alnumenviron_sys_nerr_end__iobchmodstrncpyqsortatexitmemcmprecvbindstrtoulendpwenttouppertzsetstrpbrkunamefwritepipetolowermemcpystrchrgmtimereaddirfflushstrcspnres_send__filbufselect_startchdirlongjmpsetjmpctimesprintfgettimeofdayaccesswritegetpeernametimereallocsignalsetlocaleexecvpgetpidgethostnamedn_expandlseekfopengeteuidinet_addr__flsbufmallocfcntlwaitpidstrerrorlstatsscanflistengetcwdfreefputsopenstrftime_exitabortgetpwnamsocketgetpwuidstrrchrunlinkrandgetservbynamestrcatdup2atolfseekatoiconnectfreadreadlinkres_mkqueryvforkgetenvexitperrorsendfprintfstrtolstrcmpprintfstrncatmemmoverecvfromrenamestrtodstrncmpfdopeninet_ntoastrncasecmpacceptreadfgetstmpnamstrlenfcloseopendirstrcpyclosedirgetsocknamegethostbyaddrgetuidstatstrstrgethostbynamememsetgetsockoptclosesrandsetsockoptlocaltimeshl_loadshl_findsymfmodsinhpowatansqrttanlog10floortanhexphypotceilatan2logcoshacosasinXFilterEventXDestroyICXTextWidthXAllocNamedColorXDrawRectangleXSetWMNormalHintsXSetClipMask_XInitImageFuncPtrsXEmptyRegionXSetInputFocusXAllocClassHintXWithdrawWindowXNextEventXFreeColormapXStringToKeysymXLookupStringXSetIOErrorHandlerXParseColorXSendEventXSetCommandXDefineCursorXOpenIMXNoOpXResizeWindowXReconfigureWMWindowXSyncXGetWMColormapWindowsXLoadFontXSetSelectionOwnerXReadBitmapFileXGetAtomNameXSetWindowBorderWidthXSetWMColormapWindowsXSetClipOriginXCopyPlaneXQueryTreeXUnionRectWithRegionXGetModifierMappingXCreateRegionXUnmapWindowXTextExtentsXCreateWindowXUngrabServerXAllocSizeHintsXLookupColorXQueryColorsXSetTSOriginXSetForegroundXSetTransientForHintXUngrabPointerXFillRectangleXDrawStringXGetIMValuesXSetWMHintsXEventsQueuedXIconifyWindowXAllocColorXQueryPointerXFreeModifiermapXDrawArcXCreateGCXFreeCursorXConvertSelectionXDestroyWindowXTranslateCoordinatesXSetClassHintXCreateICXLoadQueryFontXConfigureWindowXSetWindowBackgroundXVisualIDFromVisualXGetInputFocusXCreatePixmapXListHostsXSetIconNameXCopyAreaXSetErrorHandlerXPutImageXInternAtomXSynchronizeXMapWindowXGetVisualInfoXDrawLineXDrawLinesXKeycodeToKeysymXRefreshKeyboardMappingXChangePropertyXSetWindowColormapXDestroyRegionXFillPolygonXCreateBitmapFromDataXGetWindowAttributesXCreateColormapXBellXCreatePixmapCursorXGetGeometryXFreeColorsXSetWindowBackgroundPixmapXForceScreenSaverXFreeFontXOpenDisplayXRaiseWindowXSetWindowBorderXGContextFromGCXGetFontPropertyXMoveResizeWindowXChangeWindowAttributesXFreePixmapXUngrabKeyboardXSelectInputXGetImageXFlushXGetWindowPropertyXMoveWindowXIntersectRegionXFreeXKeysymToStringXGrabServerXDeletePropertyXClipBoxXFillArcXSetWMClientMachineXCreateImageXRectInRegionXQLengthXSetWMNameXGrabKeyboardXStringListToTextPropertyXFillRectanglesXGrabPointerXmbLookupStringXFreeGCXSetRegionXCreateGlyphCursorXSetWindowBorderPixmapXRootWindowmainmatherrTk_BellCmdTk_BindCmdTk_BindtagsCmdTk_ClipboardCmdTk_DestroyCmdTk_FocusCmdTk_GrabCmdTk_GridCmdTk_ImageCmdTk_LowerCmdTk_OptionCmdTk_PackCmdTk_PlaceCmdTk_RaiseCmdTk_SelectionCmdTk_TkCmdTk_TkwaitCmdTk_UpdateCmdTk_WinfoCmdTk_WmCmdTk_ButtonCmdTk_CanvasCmdTk_CheckbuttonCmdTk_EntryCmdTk_FrameCmdTk_LabelCmdTk_ListboxCmdTk_MenuCmdTk_MenubuttonCmdTk_MessageCmdTk_RadiobuttonCmdTk_ScaleCmdTk_ScrollbarCmdTk_TextCmdTk_ToplevelCmdGridReqProcGridLostSlaveProcPackReqProcPackLostSlaveProcPlaceRequestProcPlaceLostSlaveProcTopLevelReqProcImgBmapCreateImgBmapGetImgBmapDisplayImgBmapFreeImgBmapDeleteFileMatchGIFFileReadGIFFileMatchPPMFileReadPPMFileWritePPMImgPhotoCreateImgPhotoGetImgPhotoDisplayImgPhotoFreeImgPhotoDeleteTk_CanvasTagsParseProcTk_CanvasTagsPrintProcCreateArcConfigureArcArcCoordsDeleteArcDisplayArcArcToPointArcToAreaArcToPostscriptScaleArcTranslateArcCreateBitmapConfigureBitmapBitmapCoordsDeleteBitmapDisplayBitmapBitmapToPointBitmapToAreaBitmapToPostscriptScaleBitmapTranslateBitmapCreateImageConfigureImageImageCoordsDeleteImageDisplayImageImageToPointImageToAreaScaleImageTranslateImageParseArrowShapePrintArrowShapeCreateLineConfigureLineLineCoordsDeleteLineDisplayLineLineToPointLineToAreaLineToPostscriptScaleLineTranslateLineCreatePolygonConfigurePolygonPolygonCoordsDeletePolygonDisplayPolygonPolygonToPointPolygonToAreaPolygonToPostscriptScalePolygonTranslatePolygonCreateTextConfigureTextTextCoordsDeleteTextDisplayTextTextToPointTextToAreaTextToPostscriptScaleTextTranslateTextGetTextIndexSetTextCursorGetSelTextTextInsertTextDeleteCharsCreateWinItemConfigureWinItemWinItemCoordsDeleteWinItemDisplayWinItemWinItemToPointWinItemToAreaScaleWinItemTranslateWinItemWinItemRequestProcWinItemLostSlaveProcCreateRectOvalConfigureRectOvalRectOvalCoordsDeleteRectOvalDisplayRectOvalRectToPointRectToAreaRectOvalToPostscriptScaleRectOvalTranslateRectOvalOvalToPointOvalToAreaCharSplitProcCharDeleteProcCharCleanupProcTkTextCharLayoutProcCharCheckProcToggleDeleteProcToggleCleanupProcToggleLineChangeProcToggleCheckProcMarkDeleteProcMarkCleanupProcMarkLayoutProcMarkCheckProcEmbWinRequestProcEmbWinLostSlaveProcEmbWinDeleteProcEmbWinCleanupProcEmbWinLayoutProcEmbWinCheckProcAlignParseProcAlignPrintProcTcl_AppendCmdTcl_ArrayCmdTcl_BreakCmdTcl_CaseCmdTcl_CatchCmdTcl_ClockCmdTcl_ConcatCmdTcl_ContinueCmdTcl_ErrorCmdTcl_EvalCmdTcl_ExitCmdTcl_ExprCmdTcl_FileEventCmdTcl_ForCmdTcl_ForeachCmdTcl_FormatCmdTcl_GlobalCmdTcl_HistoryCmdTcl_IfCmdTcl_IncrCmdTcl_InfoCmdTcl_InterpCmdTcl_JoinCmdTcl_LappendCmdTcl_LindexCmdTcl_LinsertCmdTcl_ListCmdTcl_LlengthCmdTcl_LoadCmdTcl_LrangeCmdTcl_LreplaceCmdTcl_LsearchCmdTcl_LsortCmdTcl_PackageCmdTcl_ProcCmdTcl_RandomCmdTcl_RegexpCmdTcl_RegsubCmdTcl_RenameCmdTcl_ReturnCmdTcl_ScanCmdTcl_SetCmdTcl_SplitCmdTcl_StringCmdTcl_SubstCmdTcl_SwitchCmdTcl_TraceCmdTcl_UnsetCmdTcl_UplevelCmdTcl_UpvarCmdTcl_WhileCmdTcl_AfterCmdTcl_CdCmdTcl_CloseCmdTcl_EofCmdTcl_FblockedCmdTcl_FconfigureCmdTcl_FileCmdTcl_FlushCmdTcl_GetsCmdTcl_GlobCmdTcl_OpenCmdTcl_PidCmdTcl_PutsCmdTcl_PwdCmdTcl_ReadCmdTcl_SeekCmdTcl_SocketCmdTcl_TellCmdTcl_TimeCmdTcl_UpdateCmdTcl_VwaitCmdTclUnsupported0CmdTcl_ExecCmdTcl_SourceCmdCommonBlockModeProcFileCloseProcFilePipeInputProcFilePipeOutputProcFileSeekProcPipeCloseProcTcpBlockModeProcTcpCloseProcTcpInputProcTcpOutputProcTcpGetOptionProcmatherrExprUnaryFuncacosasinatanExprBinaryFuncatan2ceilcoscoshexpfloorfmodhypotloglog10powsinsinhsqrttantanhExprAbsFuncExprDoubleFuncExprIntFuncExprRoundFuncclean_up_and_diebus_recvrecv_packetssip_recvload_cache_entryxremove_interfacerebuild_interfacetimed_send_advertui_generate_portgenerate_idui_generate_addressgetemailaddresscreatesessionui_check_addressgethostaddrgetusernameui_stop_session_adgetdaynamegetmonnamewebtosave_www_data_to_filestop_www_loadingui_sd_listenui_lookup_hostui_sip_send_msgui_quitui_set_passphraseui_get_passphraseui_add_keyui_delete_keyui_find_key_by_nameui_load_keysui_save_keysui_write_crypted_fileDeleteWindowsExitProcTkDeadAppCmdDisplaySetupProcDisplayCheckProcFreeScreenInfoClipboardLostSelClipboardHandlerClipboardAppHandlerClipboardWindowHandlerWaitVariableProcWaitVisibilityProcWaitWindowProcDelayedMotionProcWindowEventProcFocusMapProcGrabRestrictProcGrabWinEventProcArrangeGridGridBagStructureProcDestroyGridBagArrangePackingPackStructureProcDestroyPackerSlaveStructureProcMasterStructureProcRecomputePlacementHandleTclCommandLostSelectionSelGetProcfreeTk_SendCmdDeleteProcSendRestrictProcTimeoutProcSendEventProcAppendErrorProcAllocXIdWindowIdCleanupCheckRestrictProcWindowIdCleanup2TopLevelEventProcUpdateGeometryInfoWaitRestrictProcWaitTimeoutProcButtonCmdDeletedProcButtonWidgetCmdButtonEventProcDisplayButtonButtonTextVarProcButtonVarProcButtonImageProcButtonSelectImageProcEntryCmdDeletedProcEntryWidgetCmdEntryEventProcEntryFetchSelectionEntryLostSelectionEntryTextVarProcDisplayEntryDestroyEntryEntryBlinkProcFrameCmdDeletedProcFrameWidgetCmdFrameEventProcMapFrameDisplayFrameDestroyFrameListboxCmdDeletedProcListboxWidgetCmdListboxEventProcListboxFetchSelectionListboxLostSelectionDisplayListboxDestroyListboxMenuCmdDeletedProcMenuWidgetCmdMenuEventProcDestroyMenuEntryComputeMenuGeometryMenuVarProcMenuImageProcMenuSelectImageProcDisplayMenuDestroyMenuMenuButtonCmdDeletedProcMenuButtonWidgetCmdMenuButtonEventProcMenuButtonTextVarProcMenuButtonImageProcDisplayMenuButtonDestroyMenuButtonMessageCmdDeletedProcMessageWidgetCmdMessageEventProcMessageTextVarProcDisplayMessageDestroyMessageScaleCmdDeletedProcScaleWidgetCmdScaleEventProcScaleVarProcDisplayScaleDestroyScaleScrollbarCmdDeletedProcScrollbarWidgetCmdScrollbarEventProcDisplayScrollbarDestroyScrollbarCanvasCmdDeletedProcCanvasWidgetCmdCanvasEventProcCanvasBindProcCanvasFetchSelectionDisplayCanvasDestroyCanvasCanvasBlinkProcCanvasLostSelectionImgBmapCmdDeletedProcImgBmapCmdImgPhotoCmdDeletedProcImgPhotoCmdDisposeInstanceDisposeColorTableTextCmdDeletedProcTextWidgetCmdTextEventProcTkTextBindProcTextFetchSelectionTkTextLostSelectionDestroyTextTextBlinkProcErrorProcMaintainSlaveProcMaintainMasterProcMaintainCheckProcSelTimeoutProcSelRcvIncrProcIncrTimeoutProcImageChangedProcWinItemStructureProcDisplayTextTkTextInsertDisplayProcCharDisplayProcCharUndisplayProcCharMeasureProcCharBboxProcInsertUndisplayProcTagSortProcEmbWinStructureProcEmbWinDelayedUnmapEmbWinDisplayProcEmbWinUndisplayProcEmbWinBboxProcScrollRestrictProcTclPrecTraceProcDeleteInterpProcTclExpandParseValueFileHandlerSetupProcFileHandlerCheckProcFileHandlerExitProcFileHandlerEventProcTimerHandlerSetupProcTimerHandlerCheckProcTimerHandlerExitProcTimerHandlerEventProcBgErrorDeleteProcHandleBgErrorsAfterCleanupProcAfterProcVwaitVarProcFileExitProcFileNameCleanupStringFindStringCreateArrayFindOneWordFindOneWordCreateArrayCreateBogusFindBogusCreateDeleteChannelTableChannelEventScriptInvokerCloseChannelsOnExitFlushEventProcChannelEventDeleteProcChannelHandlerEventProcChannelHandlerSetupProcChannelHandlerCheckProcChannelEventSourceExitProcLinkTraceProcPreserveExitProcTcpAcceptSortCompareProcTraceVarProcEnvTraceProcEnvExitProcAliasCmdSlaveObjectDeleteProcSlaveObjectCmdSlaveRecordDeleteProcAliasCmdDeleteProcMasterRecordDeleteProcTcpAcceptCallbacksDeleteProcAcceptCallbackProcTcpServerCloseProcLoadExitProcLoadCleanupProcProcDeleteProcInterpProcFreeCurrentDirFreeExecutableName__gcc_plt_call__do_global_dtorsXZ]XZ]XZ]XZ]d@"Z]> ZZ]> ZZ]9 Z8 =@Y :Z @Z@ ZZZ] ZZ @"ZY :ZZ@= ZZZ@= Z ZY :Z]ya: =]: =]  : =@]ZBu ZZZZ ZZ]ya: =]: =]  : = @]ZB ZZZM ZZY :}@]Be]yZZ5@*Z@ya AZ@ya AZ]ya A @Z@] Z]: =] y a: =]Y(ZYY8Z@] Z]: =] y a: =]Y(Z YY8Z]Y Z @*Z@YA AZ@YA AZ]YA A @ ZZmZ?#Z>B @V   @  A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  :R @@@ @]@@@W@@@_@/@@ @V7@ @V@w@ @ : @V   @A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A ˡF ! !V @ B*  @ Z ]! =]! =]! =]! =]! =]! =]! =]! =]! =]! =]! =]! =]! =]! =]! =]! =]! =]! =]! =]! =]! =]! =]! =]! =]! =]! =]! =]! =]! =]! =]! =]` =@ :]@JJ k?tickcrossuparrowdownarrowphonemaileyeaudiowbwwwtextunknownclockucltoolsbullet0bullet1broadcastmeetingtestsdrbus recv errorWarning: 2K local conf bus message truncated 224.1.127.255connectDest Address problem setsockopt ttlttl: %d bus sendLCB/1.0sdr instance interface visible OK, mapping i/f envDISPLAYTTL problem on LCB: message ignored someone else Unknown LCB message type received LCB/1.0 sdr instance %u %s %s %saudiowhiteboardvideosocketsocket fd too large (%d) Binding socket %d to address/port %s/%d bindAddress: %x, Port: %d setsockopt - IP_ADD_MEMBERSHIPConnecting socket %d to address/port %s/%d connectDest Address problem setsockopt ttlttl: %d cryptrn=%lu %lu %lu %s %u %u %sk=trustedsdr:corrupted cache file: %s gethostname failed! gethostbyname failed (hostname='%s'! noname-s-d1-no_gui-logguiGUINO_GUIlogTRUEFALSE224.2.127.254224.2.127.253load_cache_entryload_from_cachewrite_cacheSdr: %s build_interface firstreshow_sessions [set showwhich]recv errorWarning: 2K announcement truncated untrustedset %s(%d) [clock format %u -format {%%d %%b %%y %%H:%%M %%Z}]v=0 Too many email fields Too many phones (!) Too many bandwidth fields Too many times Too many repeats Too many keys Sdr: too many media sdr: too many attributes to fit in available space decoding cache data! Error decoding cache data Failure at byte %ld reset_media%s trustrecvkeysessiondescNo channel field received! Unacceptably long channel field received %s %s %s%u %utfromttostarttime(%d)%uendtime(%d)repeat(%d,%d)rctr(%d)%dIllegal infinite session with multiple time fields tfrom(0)0tto(0)rctr(0)starttime(0)endtime(0)multicastUnacceptably long originator field received %s %s %s %s %s %screatormodtimecreatetimecreateaddr%s%s%s%xadvertidsourceheardfromset timeheard [clock format %u -format {%%d %%b %%y %%H:%%M %%Z}]uriphone(%d)email(%d)bw(%d)keysessvarsUnacceptably long media field received %s %d %s %smediavarsportprotofmtmediattlmediaaddrset_mediaset_media[%d] for session %s: %s recvttlrecvsd_addrrecvsd_portadd_to_listadd_to_list failed for session %s: %s INsdr: expected network type IN, got %s IP4sdr: expected address type IP4, got %s sending %s sending encrypted session ----- sending ad to sock %d, ttl %d WARNING: received key containing Tcl special chars |tldplugtutpluginsnode15node14node13node12node11node10node9node8node7node6node5node4node3node2node1sdrchangesbugstoolsmboneabout

Frequently Asked Questions (FAQ) on the Multicast Backbone (MBONE)

Steve Casner, casner@isi.edu, 22-Dec-94

*** This file is ftp://ftp.isi.edu/mbone/faq.txt ***
*** Corrections and Additions Requested ***

Note: This file has badly needed updating since the 6-May-93 version. Some of the most glaring errors have been fixed here, but more rewriting is required. It is also intended that this text form and an HTML form will be generated from a common source. Some other sources of info are:
http://www.research.att.com/mbone-faq.html
ftp://taurus.cs.nps.navy.mil/pub/mbmg/mbone.html
ftp://genome-ftp.stanford.edu/pub/mbone/mbone-connect
http://www.cl.cam.ac.uk/mbone/
http://www.eit.com/techinfo/mbone/mbone.html

What is the MBONE?

The MBONE is an outgrowth of the first two IETF "audiocast" experiments in which live audio and video were multicast from the IETF meeting site to destinations around the world. The idea is to construct a semi-permanent IP multicast testbed to carry the IETF transmissions and support continued experimentation between meetings. This is a cooperative, volunteer effort.

The MBONE is a virtual network. It is layered on top of portions of the physical Internet to support routing of IP multicast packets since that function has not yet been integrated into many production routers. The network is composed of islands that can directly support IP multicast, such as multicast LANs like Ethernet, linked by virtual point-to-point links called "tunnels". The tunnel endpoints are typically workstation-class machines having operating system support for IP multicast and running the "mrouted" multicast routing daemon.

How do IP multicast tunnels work?

IP multicast packets are encapsulated for transmission through tunnels, so that they look like normal unicast datagrams to intervening routers and subnets. A multicast router that wants to send a multicast packet across a tunnel will prepend another IP header, set the destination address in the new header to be the unicast address of the multicast router at the other end of the tunnel, and set the IP protocol field in the new header to be 4 (which means the next protocol is IP). The multicast router at the other end of the tunnel receives the packet, strips off the encapsulating IP header, and forwards the packet as appropriate.

Previous versions of the IP multicast software (before March 1993) used a different method of encapsulation based on an IP Loose Source and Record Route option. This method remains an option in the new software for backward compatibility with nodes that have not been upgraded. In this mode, the multicast router modifies the packet by appending an IP LSRR option to the packet's IP header. The multicast destination address is moved into the source route, and the unicast address of the router at the far end of the tunnel is placed in the IP Destination Address field. The presence of IP options, including LSRR, may cause modern router hardware to divert the tunnel packets through a slower software processing path, causing poor performance. Therefore, use of the new software and the IP encapsulation method is strongly encouraged.

What is the topology of the MBONE?

We anticipate that within a continent, the MBONE topology will be a combination of mesh and star: the backbone and regional (or mid-level) networks will be linked by a mesh of tunnels among mrouted machines located primarily at interconnection points of the backbones and regionals. Some redundant tunnels may be configured with higher metrics for robustness. Then each regional network will have a star hierarchy hanging off its node of the mesh to fan out and connect to all the customer networks that want to participate.

Between continents there will probably be only one or two tunnels, preferably terminating at the closest point on the MBONE mesh. In the US, this may be on the Ethernets at the two FIXes (Federal Internet eXchanges) in California and Maryland. But since the FIXes are fairly busy, it will be important to minimize the number of tunnels that cross them. This may be accomplished using IP multicast directly (rather than tunnels) to connect several multicast routers on the FIX Ethernet.

How is the MBONE topology going to be set up and coordinated?

The primary reason we set up the MBONE e-mail lists (see below) was to coordinate the top levels of the topology (the mesh of links among the backbones and regionals). This must be a cooperative project combining knowledge distributed among the participants, somewhat like Usenet. The goal is to avoid loading any one individual with the responsibility of designing and managing the whole topology, though perhaps it will be necessary to periodically review the topology to see if corrections are required.

The intent is that when a new regional network wants to join in, they will make a request on the appropriate MBONE list, then the participants at "close" nodes will answer and cooperate in setting up the ends of the appropriate tunnels. To keep fanout down, sometimes this will mean breaking an existing tunnel to inserting a new node, so three sites will have to work together to set up the tunnels.

To know which nodes are "close" will require knowledge of both the MBONE logical map and the underlying physical network topology, for example, the physical T3 NSFnet backbone topology map combined with the network providers' own knowledge of their local topology.

Within a regional network, the network's own staff can independently manage the tunnel fanout hierarchy in conjunction with end-user participants. New end-user networks should contact the network provider directly, rather than the MBONE list, to get connected.

What is the anticipated traffic level?

The traffic anticipated during IETF multicasts is 100-300Kb/s, so 500Kb/s seems like a reasonable design bandwidth. Between IETF meetings, most of the time there will probably be no audio or video traffic, though some of the background session/control traffic may be present. A guess at the peak level of experimental use might be 5 simultaneous voice conversations (64Kb/s each). Clearly, with enough simultaneous conversations, we could exceed any bandwidth number, but 500Kb/s seems reasonable for planning.

Note that the design bandwidth must be multiplied by the number of tunnels passing over any given link since each tunnel carries a separate copy of each packet. This is why the fanout of each mrouted node should be no more than 5-10 and the topology should be designed so that at most 1 or 2 tunnels flow over any T1 line.

While most MBONE nodes should connect with lines of at least T1 speed, it will be possible to carry restricted traffic over slower speed lines. Each tunnel has an associated threshold against which the packet's IP time-to-live (TTL) value is compared. By convention in the IETF multicasts, higher bandwidth sources such as video transmit with a smaller TTL so they can be blocked while lower bandwidth sources such as compressed audio are allowed through.

Why should I (a network provider) participate?

To allow your customers to participate in IETF audiocasts and other experiments in packet audio/video, and to gain experience with IP multicasting for a relatively low cost.

What technical facilities and equipment are required for a network provider to join the MBONE?

Each network-provider participant in the MBONE provides one or more IP multicast routers to connect with tunnels to other participants and to customers. The multicast routers are typically separate from a network's production routers since most production routers don't yet support IP multicast. Most sites use workstations running the mrouted program, but the experimental MOSPF software for Proteon routers is an alternative (see MOSPF question below).

It is best if the workstations can be dedicated to the multicast routing function to avoid interference from other activities and so there will be no qualms about installing kernel patches or new code releases on short notice. Since most MBONE nodes other than endpoints will have at least three tunnels, and each tunnel carries a separate (unicast) copy of each packet, it is also useful, though not required, to have multiple network interfaces on the workstation so it can be installed parallel to the unicast router for those sites with configurations like this:

		   +----------+
		   | Backbone |
		   |   Node   |
		   +----------+
			|
    ------------------------------------------ External DMZ Ethernet
	     |               |
	+----------+    +----------+
	|  Router  |    |  mrouted |
	+----------+    +----------+
	     |               |
    ------------------------------------------ Internal DMZ Ethernet

(The "DMZ" Ethernets borrow that military term to describe their role as interface points between networks and machines controlled by different entities.) This configuration allows the mrouted machine to connect with tunnels to other regional networks over the external DMZ and the physical backbone network, and connect with tunnels to the lower-level mrouted machines over the internal DMZ, thereby splitting the load of the replicated packets. (The mrouted machine would not do any unicast forwarding.)

Note that end-user sites may participate with as little as one workstation that runs the packet audio and video software and has a tunnel to a network-provider node.

What skills are needed to participate and how much time might have to be devoted to this?

The person supporting a network's participation in the MBONE should have the skills of a network engineer, but a fairly small percentage of that person's time should be required. Activities requiring this skill level would be choosing a topology for multicast distribution with in the provider's network and analyzing traffic flow when performance problems are identified.

To set up and run an mrouted machine will require the knowledge to build and install operating system kernels. If you would like to use a hardware platform other than those currently supported, then you might also contribute some software implementation skills!

We will depend on participants to read mail on the appropriate mbone mailing list and respond to requests from new networks that want to join and are "nearby" to coordinate the installation of new tunnel links. Similarly, when customers of the network provider make requests for their campus nets or end systems to be connected to the MBONE, new tunnel links will need to be added from the network provider's multicast routers to the end systems (unless the whole network runs MOSPF).

Part of the resources that should be committed to participate would be for operations staff to be aware of the role of the multicast routers and the nature of multicast traffic, and to be prepared to disable multicast forwarding if excessive traffic is found to be causing trouble. The potential problem is that any site hooked into the MBONE could transmit packets that cover the whole MBONE, so if it became popular as a "chat line", all available bandwidth could be consumed. Steve Deering plans to implement multicast route pruning so that packets only flow over those links necessary to reach active receivers; this will reduce the traffic level. This problem should be manageable through the same measures we already depend upon for stable operation of the Internet, but MBONE participants should be aware of it.

Which workstation platforms can support the mrouted program?

The most convenient platform is a Sun SPARCstation simply because that is the machine used for mrouted development. An older machine (such as a SPARC-1 or IPC) will provide satisfactory performance as long as the tunnel fanout is kept in the 5-10 range. The platforms for which software is available:
    Machines             Operating Systems       Network Interfaces
    --------             -----------------       ------------------
    Sun SPARC            SunOS 4.1.1,2,3         ie, le, lo
    Vax or Microvax      4.3+ or 4.3-tahoe       de, qe, lo
    Decstation 3100,5000 Ultrix 3.1c, 4.1, 4.2a  ln, se, lo
    Silicon Graphics     All ship with multicast
There is an interested group at DEC that may get the software running on newer DEC systems with Ultrix and OSF/1. Also, some people have asked about support for the RS-6000 and AIX or other platforms. Those interested could use the mbone list to coordinate collaboration on porting the software to these platforms!

An alternative to running mrouted is to run the experimental MOSPF software in a Proteon router (see MOSPF question below).

Where can I get the IP multicast software and mrouted program?

The IP multicast software is available by anonymous FTP from the vmtp-ip directory on host gregorio.stanford.edu. Here's a snapshot of the files:
	ipmulti-pmax31c.tar
	ipmulti-sunos41x.tar.Z	    Binaries & patches for SunOS 4.1.1,2,3
	ipmulticast-ultrix4.1.patch
	ipmulticast-ultrix4.2a-binary.tar
	ipmulticast-ultrix4.2a.patch
	ipmulticast.README	    [** Warning: out of date **]
	ipmulticast.tar.Z	    Sources for BSD

### Release 3.3 of the SunOS kernel multicast extensions was made in
### late August, but was not put on gregorio like previous releases.
### Instead, it is on parcftp.xerox.com, directory pub/net-research,
### file ipmulti3.3-sunos413x.tar.Z  This release has multicast
### pruning and several other major improvements over previous
### releases, so upgrading is encouraged.
You don't need kernel sources to add multicast support. Included in the distributions are files (sources or binaries, depending upon the system) to modify your BSD, SunOS, or Ultrix kernel to support IP multicast, including the mrouted program and special multicast versions of ping and netstat.

Silicon Graphics includes IP multicast as a standard part of their operating system. The mrouted executable and ip_mroute kernel module are not installed by default; you must install the eoe2.sw.ipgate subsystem and "autoconfig" the kernel to be able to act as a multicast router. In the IRIX 4.0.x release, there is a bug in the kernel code that handles multicast tunnels; an unsupported fix is available via anonymous ftp from sgi.com in the sgi/ipmcast directory. See the README there for details on installing it.

IP multicast is also included in all Solaris 2 releases. Solaris 2.3 out of the box supports the non-pruning version of mrouted (mrouted version 2.0-2.2), but mrouted is not included with Solaris so you must fetch the mrouted sources from the multicast software distribution and compile them. Solaris 2.2 requires patches to run mrouted, available from ftp.uoregon.edu in the directory /pub/Solaris2.x/src/MBONE/Solaris2.x/Kernel.

IP multicast is supported in BSD 4.4.

The most common problem encountered when running this software is with hosts that respond incorrectly to IP multicasts. These responses typically take the form of ICMP network unreachable, redirect, or time-exceeded error messages, which are a waste of bandwidth and can cause an error in the packet send operation executed by a multicast source. The result may be dropouts in an audio or video stream. These responses are in violation of the current IP specification and, with luck, will disappear over time.

What documentation is available?

Documentation on the IP multicast software is included in the distribution on gregorio.stanford.edu (ipmulticast.README). RFC1112 specifies the "Host Extensions for IP Multicasting".

Multicast routing algorithms are described in the paper "Multicast Routing in Internetworks and Extended LANs" by S. Deering, in the Proceedings of the ACM SIGCOMM '88 Conference.

There is an article in the June 1992 ConneXions about the first IETF audiocast from San Diego, and a later version of that article is in the July 1992 ACM SIGCOMM CCR. A reprint of the latter article is available by anonymous FTP from venera.isi.edu in the file pub/ietf-audiocast-article.ps. There is no article yet about later IETF audio/videocasts.

Where can I get a map of the MBONE?

The most recent "complete" map of the MBONE is available in two Postscript files are available on parcftp.xerox.com:
        /pub/net-research/mbone-map-{big,small}.ps
The small one fits on one page but is hard to read, and the big one is four pages that have to be taped together for viewing. This map was produced from topology information collected automatically from all MBONE nodes that respond to remote queries for mapping information (some are running ancient versions of mrouted that do not respond, and some are hidden by firewalls or routing boundaries). Pavel Curtis at Xerox PARC has added the mechanisms to automatically collect the map data and produce the map. (Thanks also to Paul Zawada of NCSA who manually produced an earlier map of the MBONE.)

The MBONE is now large enough that it is hard to show all nodes and links on one graph. To give a higher level view of the MBONE, there is another map that shows only the major links and nodes in a roughly geographical representation that was created manually by Steve Casner. It is available from ftp.isi.edu:

	mbone/mbone-topology.ps

What is DVMRP?

DVMRP is the Distance Vector Multicast Routing Protocol; it is the routing protocol implemented by the mrouted program. An earlier version of DVMRP is specified in RFC-1075. However, the version implemented in mrouted is quite a bit different from what is specified in that RFC (different packet format, different tunnel format, additional packet types, and more). It maintains topological knowledge via a distance-vector routing protocol (like RIP, described in RFC-1058), upon which it implements a multicast forwarding algorithm called Truncated Reverse Path Broadcasting. DVMRP suffers from the well-known scaling problems of any distance-vector routing protocol.

What is MOSPF?

MOSPF is the IP multicast extension to the OSPF routing protocol, currently an Internet Draft. John Moy has implemented MOSPF for the Proteon router. A network of routers running MOSPF can forward IP multicast packets directly, sending no more than one copy over any link, and without the need for any tunnels. This is how IP multicasting within a domain is supposed to work.

Can MOSPF and DVMRP interoperate?

At the Boston IETF, John Moy agreed to add support for DVMRP to his MOSPF implementation. He hopes to have this completed "well in advance of the next IETF". When it is finished, you will be able to set up a DVMRP tunnel from an mrouted to Proteon a router, glueing together the DVMRP with MOSPF domains (the MOSPF domains will look pretty like ethernets to the multicast topology).

The advantages to linking DVMRP with MOSPF are: fewer configured tunnels, and less multicast traffic on the links inside the MOSPF domain. There are also a couple potential drawbacks: increasing the size of DVMRP routing messages, and increasing the number of external routes in the OSPF systems. However, it should be possible to alleviated these drawbacks by configuring area address ranges and by judicious use of MOSPF default routing.

How do I join the MBONE?

STEP 1: If you are an end-user site (e.g., a campus), please contact your network provider. If your network provider is not participating in the MBONE, you can arrange to connect to some nearby point that is on the MBONE, but it is far better to encourage your network provider to participate to avoid overloading links with duplicate tunnels to separate end nodes. Below is a list of some network providers who are participating in the MBONE, but this list is likely not to be complete.
	AlterNet	mbone-request@uunet.uu.net
	CA*net		canet-eng@canet.ca
	CERFnet		mbone@cerf.net
	CICNet		mbone@cic.net
	CONCERT		mbone@concert.net
	Cornell		swb@nr-tech.cit.cornell.edu
	JvNCnet		multicast@jvnc.net
	Los Nettos	prue@isi.edu
	NCAR		mbone@ncar.ucar.edu
	NCSAnet		mbone@cic.net
	NEARnet		nearnet-eng@nic.near.net
	OARnet		oarnet-mbone@oar.net
	ONet		onet-eng@onet.on.ca
	PSCnet		pscnet-admin@psc.edu
	PSInet		mbone@nisc.psi.net
	SESQUINET	mbone@sesqui.net
	SDSCnet		mbone@sdsc.edu
	Sprintlink	mbone@sprintlink.net
	SURAnet		multicast@sura.net
	UNINETT		mbone-no@uninett.no
If you are a network povider, send a message to the -request address of the mailing list for your country to be added to that list for purposes of coordinating setup of tunnels, etc:
	Australia:	mbone-oz-request@internode.com.au
	Austria:	mbone-at-request@noc.aco.net
	Canada:	 	canet-mbone-request@canet.ca
	Denmark:	mbone-request@daimi.aau.dk
	France:		mbone-fr-request@inria.fr
	Germany:	mbone-de-request@informatik.uni-erlangen.de
	Italy:		mbone-it-request@nis.garr.it
	Japan:		mbone-jp-request@wide.ad.jp
	Korea:		mbone-korea-request@cosmos.kaist.ac.kr
	Netherlands:	mbone-nl-request@nic.surfnet.nl
	New Zealand:	mbone-nz-request@waikato.ac.nz
	Singapore:	mbone-sg-request@technet.sg
	UK:		mbone-uk-request@cs.ucl.ac.uk
If your country is not listed, send your request to the appropriate regional sublist:
	Europe:		mbone-eu-request@sics.se
	N. America:	mbone-na-request@isi.edu
	other:		mbone-request@isi.edu
These lists are primarily aimed at network providers who would be the top level of the MBONE organizational and topological hierarchy. The mailing list is also a hierarchy; mbone@isi.edu forwards to the regional lists, then those lists include expanders for network providers and other institutions. Mail of general interest should be sent to mbone@isi.edu, while regional topology questions should be sent to the appropriate regional list.

Individual networks may also want to set up their own lists for their customers to request connection of campus mrouted machines to the network's mrouted machines. Some that have done so were listed above.

STEP 2: Set up an mrouted machine, build a kernel with IP multicast extensions added, and install the kernel and mrouted; or, install MOSPF software in a Proteon router.

STEP 3: Send a message to the mbone list for your region asking to hook in, then coordinate with existing nodes to join the tunnel topology.

How is a tunnel configured?

Mrouted automatically configures itself to forward on all multicast-capable interfaces, i.e. interfaces that have the IFF_MULTICAST flag set (excluding the loopback "interface"), and it finds other mrouteds directly reachable via those interfaces. To override the default configuration, or to add tunnel links to other mrouteds, configuration commands may be placed in /etc/mrouted.conf. There are two types of configuration command:
        phyint    [disable]   [metric ] [threshold ]

        tunnel   [metric ] [threshold ]
The phyint command can be used to disable multicast routing on the physical interface identified by local IP address , or to associate a non-default metric or threshold with the specified physical interface. Phyint commands should precede tunnel commands.

The tunnel command can be used to establish a tunnel link between local IP address and remote IP address , and to associate a non-default metric or threshold with that tunnel. The tunnel must be set up in the mrouted.conf files of both ends before it will be used. The keyword "srcrt" can be added just before the keyword "metric" to choose source routing for the tunnel if necessary because the other end has not yet upgraded to use IP encapsulation. Upgrading is highly encouraged. If the methods don't match at the two ends, the tunnel will appear to be up according to mrouted typeouts, but no multicast packets will flow.

The metric is the "cost" associated with sending a datagram on the given interface or tunnel; it may be used to influence the choice of routes. The metric defaults to 1. Metrics should be kept as small as possible, because mrouted cannot route along paths with a sum of metrics greater than 31. It is recommended that the metric of all links be set to 1 unless you are specifically trying to force traffic to take another path. On such a "backup tunnel", the metric should be the sum of metrics on primary path + 1.

The threshold is the minimum IP time-to-live required for a multicast datagram to be forwarded to the given interface or tunnel. It is used to control the scope of multicast datagrams. (The TTL of forwarded packets is only compared to the threshold, it is not decremented by the threshold. Every multicast router decrements the TTL by 1.) The default threshold is 1.

Since the multicast routing protocol implemented by mrouted does not yet prune the multicast delivery trees based on group membership (it does something called "truncated broadcast", in which it prunes only the leaf subnets off the broadcast trees), we instead use a kludge known as "TTL thresholds" to prevent multicasts from traveling along unwanted branches. This is NOT the way IP multicast is supposed to work; MOSPF does it right, and mrouted will do it right some day.

Before the November 1992 IETF we established the following thresholds. The "TTL" column specifies the originating IP time-to-live value to be used by each application. The "thresh" column specifies the mrouted threshold required to permit passage of packets from the corresponding application, as well as packets from all applications above it in the table:

						TTL     thresh
						---     ------
	IETF chan 1 low-rate GSM audio		255	 224
	IETF chan 2 low-rate GSM audio		223	 192
	IETF chan 1 PCM audio			191	 160
	IETF chan 2 PCM audio			159	 128
	IETF chan 1 video			127	  96
	IETF chan 2 video			 95	  64
	local event audio			 63	  32
	local event video			 31	   1
It is suggested that a threshold of 128 be used initially, and then raise it to 160 or 192 only if the 64 Kb/s voice is excessive (GSM voice is about 18 Kb/s), or lower it to 64 to allow video to be transmitted to the tunnel.

Mrouted will not initiate execution if it has fewer than two enabled vifs, where a vif (virtual interface) is either a physical multicast-capable interface or a tunnel. It will log a warning if all of its vifs are tunnels, based on the reasoning that such an mrouted configuration would be better replaced by more direct tunnels (i.e., eliminate the middle man). However, to create a hierarchical fanout for the MBONE, we will have mrouted configurations that consist only of tunnels.

Once you have edited the mrouted.conf file, you must run mrouted as root. See ipmulticast.README for more information.

Have there been any movements towards productizing any of this?

The network infrastructure will require resource management mechanisms to provide low delay service to real-time applications on any significant scale. That will take a few years. Until that time, product-level robustness won't be possible. However, vendors are certainly interested in these applications, and products may be targeted initially to LAN operation.

IP multicast host extensions are being added to some vendors' operating systems. That's one of the first steps. Proteon has announced IP multicast support in their routers. No network provider is offering production IP multicast service yet.

What hardware platforms support the audio and video applications?

Most of the applications have been ported to the DEC 5000, DEC Alpha, HP 9000/700, SGI Indy and Indigo, and Sun SPARCstation. Some applications are also supported on IBM RS/6000 and on Intel 486 platforms running BSD UNIX. No additional hardware is required to receive audio and video on those systems that have audio built in because the rest is done in software. To send audio requires a microphone; to send video requires a camera and video capture device which are only built-in on a few of the systems. For example, the VideoPix card has been used on the SPARC, but is no longer for sale. The newer SunVideo card is supported under Solaris 2.x, but there is no device driver for SunOS 4.1.x (at least not yet). See the descriptions of video applications below for a list of the capture boards supported by each program.

For the camera, any camcorder with a video output will do. The wide-angle range is most important for monitor-top mounting. There is also a small (about 2x2x5 inches) monochrome CCD camera suitable for desktop video conference applications available for around $200 from Howard Enterprises Inc, 545 Calles San Pablo, Camarillo, CA 93102, phone 805-383-7444. Subjectively, it seems to give a picture somewhat less crisp than a typical camcorder, but sufficient for 320x240 resolution software video algorithms. There is also a color model and an infrared one for low light, with an IR LED for illumination.

What operating system support is required?

You can run the audio and video applications point-to-point between two hosts using normal unicast addresses and routing, but to conference with multiple hosts, each host must run an operating system kernel with IP multicast support. IP multicast invokes Ethernet multicast to reach multiple hosts on the same subnet; to link multiple local subnets or to connect to the MBONE you need a multicast router as described above.

IP multicast is included in the standard IRIX kernels for SGI machines, in Solaris 2.3 and later, and in OSF/1 2.0. You can pick up free IP multicast software and add it to AIX 3.2, HP-UX, SunOS 4.1.x and Ultrix as described above. For PC machines running DOS or Windows, IP multicast support is included in the current release of the PCTCP package from FTP Software, but the application programs are still in development. No IP multicast support is available yet for NeXT or Macintosh.

The IP multicast kernel software releases for AIX, HP-UX, SunOS, and Ultrix include a patch for the module in_pcb.c. This patch allows demultiplexing of separate multicast addresses so that multiple copies of vat can be run for different conferences at the same time.

If you run a SunOS 4.1.x kernel, you should make sure that the kernel audio buffer size variable is patched from the standard value of 1024 to be 160 decimal to match the audio packet size for minimum delay. The IP multicast software release includes patched versions of the audio driver modules, but if for some reason you can't use them, you can use adb to patch the kernel as shown below. These instructions are for SunOS 4.1.1 and 4.1.2; change the variable name to amd_bsize for 4.1.3, or Dbri_recv_bsize for the SPARC 10:

	adb -k -w /vmunix /dev/mem
	audio_79C30_bsize/W 0t160	(to patch the running kernel)
	audio_79C30_bsize?W 0t160	(to patch kernel file on disk)
	
If the buffer size is incorrect, there will be bad breakup when sound from two sites gets mixed for playback.

What is the data rate produced by the audio and video applications?

The audio coding provided by the built-in audio hardware on most systems produces 64 Kb/s PCM audio, which consumes 68-78 Kb/s on the network with packet overhead. The audio applications implement software compression for reduced data rates (36 Kb/s ADPCM, 17 Kb/s GSM, and 9 Kb/s LPC including overhead).

For the slow-frame-rate video prevalent on the MBONE, the compression, decompression and display are all done in software. The data rate is typically 25-128 Kb/s, with the maximum established by a bandwidth limit slider. Higher data rates may be used with a small TTL to keep the traffic within the local area. Support for hardware compression boards is in development.

Where can I get the audio applications?

The most popular application on the MBONE is the LBL audio tool "vat". A beta release of vat is available by anonymous FTP from ftp.ee.lbl.gov in the directory conferencing/vat where you will find tar files for the various systems supported:
	decalpha-vat.tar.Z	DEC Alpha
	decmips-vat.tar.Z	DEC 5000
	hp-vat.tar.Z		HP 9000/700
	i386-vat.tar.Z		intel 386/486 BSD
	sgi-vat.tar.Z		SGI Indy, Indigo
	sun-vat.dyn.tar.Z	SPARC, dynamic libraries
	sun-vat.tar.Z		SPARC, static libraries
Included in the vat tar files are a binary and a manual entry. The authors, Van Jacobson and Steve McCanne, say the source will be released "soon". Either SPARC version will run SunOS 4.1.x. The dynamically linked version works better than the statically linked version on Solaris 2 since it will adhere to the name service policy that the user has configured. There is a problem with vat in unicast mode on Solaris 2.3 (it works fine in multicast mode). This will be fixed in the next Solaris release. In the mean time, there is a work around for the problem available by FTP from playground.sun.com in the tar file pub/solaris2/unicast-vat-workaround.tar.

MBone software for Digital Alpha workstations running OSF/1 V2.0 and newer is available at

	http://chocolate.pa.dec.com/mbone
	ftp://chocolate.pa.dec.com/mbone
In addition, a beta release of both binary and source for the UMass audio tool NEVOT, written by Henning Schulzrinne, is available by anonymous FTP from gaia.cs.umass.edu in the pub/hgschulz/nevot directory (the filename may change from version to version). NEVOT runs on the SPARCstation and on the SGI Indigo and Indy. NEVOT supports both the vat protocol and RTP protocol.

What hardware and software is required to receive video?

The video we used for the July 1992 IETF was the DVC (desktop video conferencing) program from BBN, written by Paul Milazzo and Bob Clements. This program has since become a product, called PictureWindow. Contact picwin-sales@bbn.com for more information.

For the November 1992 IETF and several events since then, we have used two other programs. The first is the "nv" (network video) program from Ron Frederick at Xerox PARC, available from parcftp.xerox.com in the file pub/net-research/nv.tar.Z. An 8-bit visual is recommended to see the full image resolution, but nv also implements dithering of the image for display on 1-bit visuals (monochrome displays). Shared memory will be used if present for reduced processor load, but display to remote X servers is also possible. On the SPARCstation, the VideoPix card is required to originate video. Sources are to available, as are binary versions for the SGI Indigo and DEC 5000 platforms.

Also available from INRIA is the IVS program written by Thierry Turletti and Christian Huitema. It uses a more sophisticated compression algorithm, a software implementation of the H.261 standard. It produces a lower data rate, but because of the processing demands the frame rate is much lower and the delay higher. System requirements: SUN SPARCstation or SGI Indigo, video grabber (VideoPix Card for SPARCstations), video camera, X-Windows with Motif or Tk toolkit. Binaries and sources are available for anonymous ftp from avahi.inria.fr in the file pub/videoconference/ivs.tar.Z or ivs_binary_sparc.tar.Z.

SDR BUGS/UNFINISHED LIST

There are many little things on the to-do list. The main big things are:

- Two-way SIP sessions should be unicast not multicast.
- Middle button on private sessions start equivalent public session.
- client/server split not yet finished
- built-in plugins can't be switched off
   - can (sort-of be overridden, but is ugly)
- sdr hangs in WWW browser during DNS lookup
- adding new admin scope zones should be automated
   + this is awaiting the client/server split
- doesn't handle SDPv2 repeat times with units "M" and "Y"
- repeat time offset lists are only handled in limited cases
- doesn't handle SDPv2 "i" fields in media
- internationalistion very patchy
- WWW browser should cache files
- Doesn't check the version field before updating entries - inefficient
- Doesn't do proper IPRA multicast address allocation
   + awaiting simulation results
- Doesn't support encrypted annoucements
- Doesn't cope properly with DNS names for multicast groups

Sdr changes log

2.3a0 8 Oct 1996 mhandley

- encryption added:
   new cache directory added
   new SAP packet format adopted
   new UI code to separate encrypted and plain text sessions
   new preferences to specify encryption groups
   new code to store encryption group keys and other config data
   QFDES code from Saleem Bhatti et al included
   many other small changes related to encryption

- bugs in calendar fixed
   repeat sessions that repeat more than 3 months were treated incorrectly

- new session interface
   can no long create sessions that repeat for time x every y seconds
   where x > y/2.

- more label changes as a result of study by Louise Clark.
  "Detailed Time" button is no more - details are shown by default.

- sdr now does also attempt to read plugins from /usr/local/etc/sdr/plugins
  and a startup file from /usr/local/etc/sdr/sdr.tcl, in addition to
  those in ~/.sdr (or ~/sdr on Windows)

2.2a23 25 Sept 1996

- bug in the order of initialisation of Xresources was causing plugins
  to be read from the wrong place.  

- Two-way call disabled in Quick Call window pending being fixed properly.

2.2a22 9 Sept 96

- dumb state initialisation bug that carried email/phone state forward
  from one session to the next fixed.

- extra bindings added to work around tk bug in listbox scrolling in the 
  sdr main window (was possible to scroll sideways even though there was a
  binding to forbid it).

- many label changed as a result of a usage study by Louise Clark, and
  extra help labels added to preferences and calendar for beginners.

- string comparisons replace "normal" comparisons in reshow_sessions
  to avoid unwanted type conversions which were causing very occasional 
  errors.

2.2a21 13 August 1996

- code added to store the PID of media tools and to produce a warning
  (on UNIX only) if the address or port is changed in a session where
  we already have media tools running.  

  This will not work (but should fail silent) on systems other than
  SunOS and Linux which have a BSD "ps" as it will default to doing "ps
  -p " unless someone adds them to the relevant switch statement in
  media_changed_warning in sdr.tcl

- editing bug fixed: sdr is now smarter about when it really needs to
  reallocate multicast addresses when you switch between TTL scope and
  Admin scope in the technical interface.

- deleted session popups are now (again) removed when you hit delete.

2.2a20 12 August 1996 mhandley@cs.ucl.ac.uk, fenner@parc.xerox.com,
                      brezak@apollo.hp.com

- admin scope editing bug on the "normal" interface fixed - default
  local scope was incorrectly getting asserted.  bug reported by
  George Michaelson.

- admin scope scope bug fixed - command bindings were slightly incorrect
  due to previously missed tk3.6/tk4 inconsistency, but had til now been
  masked by another bug.

- code added to see if we really need to re-allocate addresses when the admin
  scope is changed so that pseudo-scopes like site,region,world don't need
  to change addresses when we change between them, but really admin scopes
  do.

- minor patches to build sdr on NT 4.0b2

- repeat time handling was botched by changing starttime if it was
  earlier than today, repeat times were then calculated from right now
  as opposed to the original start.  Although I can't explain why, this
  caused sessions with repeats to show up on every single day of the
  calendar.

- if a session had multiple repeats in the same day, the second line
  would not highlight or bring up the session window

- if a session had multiple repeats in the same day, there would be
  empty space at the bottom of the calendar detail box.

- the list of bookings would not be sorted by name because it got
  sorted by aid.  removal of the sort by aid allowed it to fall back
  to the naturally sorted order of $fullix().

2.2a19 4 August 1996 mhandley@cs.ucl.ac.uk

- Old bug in determining when to allocate new addresses/ports and when
  not to because we're editing an exising session fixed yet again.

2.2a18 1 August 1996 mhandley@cs.ucl.ac.uk

- calendar TCL bug fixed - thought I got all these last year, but no...

2.2a17 30 July 96 mhandley@cs.ucl.ac.uk

- plugin mechanism extended to provide prototype support for 
  audio redundancy and for dynamic payload types.

2.2a16 3 July 96 mhandley@cs.ucl.ac.uk

- Plugin mechanism extended to allow attributes to be specified to be
  set by default for particular formats.

- Vat plugin modified to set ptime:40 attribute by default when session
  is announced.

- Code to work around pre-tk4.1 text widget line wrap bug removed from
  session creation interface (was causing session editing problems).

- Improved the SDP repeat time code:
   - improved (but still incomplete) offset handling
   - added parser for unit specification characters "d","h","m" and "s".

- Change args to ui_init to cope with changed behaviour of Tk_ParseArgv
  which now re-writes the argument list.

- SIP session creation fixed to remove spurious "0" attribute.

- Broken SIP receive code fixed - incorrect parameters were given to bind
  when CANT_MCAST_BIND was ommitted.

- Cancel button added to "Start Tool" popup.

- Calendar arrows were incorrect with multiple repeats per day and the
  last of them terminating on the next day.

- Modified cache entries to store whether or not an annoucement is 
  trusted so that spoof announcements claiming you were the originator 
  don't get re-announced but do get displayed (previous fix just 
  ignored them).

9 July 96 batie@aahz.jf.intel.com

- added extra checks to exit cleanly if we can't find our own hostname
  or address.

9 July 96 van@ee.lbl.gov

- In the process of converting sdr from using the xrand48 routines to
  'random()', I introduced a serious bug in the announcement logic.  The
  symptom is that the first two announcements are made then no more.
  The reason is that drand48 returns a double on [0..1) and random
  returns a u_int on [0..2^32) so the first randomized interval in
  timed_send_advert is huge.

- I noticed that if someone sends an announcement claiming you are the
  originator then you quit & restart sdr, you will obligingly originate
  the announcement.  I changed the receive packet handler so that it
  ignores announcements from someone else if we are the original source.

- I also added a 'sdr_delete_session_hook' to sdr.tcl (analogous to
  sdr_new_session_hook) so I could make a ~/.sdr/sdr.tcl to log when
  sessions are created & deleted (seems like an easier way to debug than
  the commented out 'puts' lines in the original).


2.2a15 3 July 96 fenner@parc.xerox.com

- Make a sip error message not look weird by not mixing printf() and
  perror() (just change it to fprintf(stderr,)

- Make announce_error() call tkerror with only one argument and
  print the actual error to stderr instead of the return from tkerror,
  and also use strncpy to not overrun statically sized buffer

- Make sdr automatically move ~/.sdr.tcl and ~/.sdr_prefs to their new
  locations, and announce that it has done so

- Get rid of an unneeded catch in sdr.tcl

-  Clicking on new media would not assign them port numbers, and
  switching back and forth between TTL and Admin scoping would produce
  ... strange results (the first time you clicked back on Admin scope,
  you would still get ttl scoped addresses)

- I also made generate_address default to 224.2.128.0/17 instead of
  224.2.0.0/16, so that the "admin scoped ttl" and the raw TTL addresses
  agreed.


2.2a14 2 July 96 fenner@parc.xerox.com

- Radically updated the web stuff to fix its history mechanism; Now
  there's one entry point to display the current point in history,
  and another entry point to add a new page to the history and make it
  current and call the other routine, so that you can't display a page
  that you don't have history for.

- Modified sd_listen.c to copy stuff into heardfrom and origsrc no
  matter what.

- Most of the other changes have to do with the new style of keeping
  the fullindex sorted.


2.2a13 5,15 June 96 mhandley
- Fixed bug in 2.2a11 preference applying after a new session arrives
  when the preferences window is up.
- Session-type attribute and user interface code added  along with icon 
  to display session type in popup window.
- Makefile and ui_init.c changed to allow separate compilation of tcl
  files for ease of development (reversing one of Van's changes).
- General session attribute handing code added.
- Intenal attribute list format changed to be newline separated to cope
  with spaces in SDP attributes.
- "tool" session attribute added to session announcements to aid debugging
  when other session directory tools become more common.
 
2.2a12 11 Jun 96 van@ee.lbl.gov

- Several ifdef's & changes to support building under Win95/WinNT.
  The Windows implementation is complete & fully functional except:
    - sip support is disabled
    - the conference bus is disabled (it would be a nop under windows
      anyway)

- Moved all config files into ~/.sdr (~/sdr under Windows) directory.
  Name of this directory can now be set with Sdr.sdrHome X resource.
  Changed filenames are:
    ~/.sdr_prefs   ->  ~/.sdr/prefs
    ~/.sdr.tcl     ->  ~/.sdr/sdr.tcl
    ~/.sdr.<lang>  ->  ~/.sdr/<lang>

- under windows, use the right button (which tk calls `button 3') for
  the 'immediate start' funtion since there is no button 2.

- replaced rand48 calls with random calls, using the random.c from
  the vic/vat distribution.  This is faster, more portable & more
  random than rand48.

- converted to release version tcl7.5/tk4.1.  Set up makefiles to
  generate lib.tcl from installed tcl/tk library files rather than
  using handbuilt lib.tcl that might be from incompatible tcl version.

- since winsock i/o works via callbacks rather than 'select', replaced
  calls to Tcl_CreateFileHandler() with calls to linksocket() (in new
  module iohander.c).  linksocket will take care of getting the winsock
  callbacks under win95/nt & will call Tcl_CreateFileHandler under unix.

- since you can get socket callbacks at any time (e.g., while other
  tcl code is being executed), most Tcl_Eval() calls needed to be
  Tcl_GlobalEval() calls to make sure they executed in the correct
  context.

- since winsock callbacks can arrive as soon as the handler is declared,
  need to create enough of the GUI to deal with callbacks *before*
  linking sockets otherwise we'll randomly crash during startup.

- tried to use new tcl7.5 clock facilities rather than localtime/strftime
  since the latter may not work on all systems that run tcl/tk
  (e.g., the Mac).  Changed C routine gettime to tcl routines gettime
  and gettimenow.  Changed '%e' in time format with %d since Microsoft
  (and Posix) don't support %e.

- got rid of 'please wait' popups when running under Windows (popup
  windows are *way* to expensive to use under Win95).

- changed the www receive code to use recv() rather than fdopen on
  the socket fd.  sockets aren't files under windows so this won't
  work and, anyway, recv is simpler and faster.

- the directory traversal code used for cache loading was very unix
  specific.  replaced it with a tcl procedure that uses tcl file
  globbing to get cache file names then calls a new C routing
  load_cache_entry() to validate & load one cache file.

- replace bcopy/bzero calls with memcpy/memset calls since former isn't
  portable to windows or most posix systems.

- added error announcement dialog box with optional traceback to the
  startup processing (otherwise you can't tell what went wrong under
  windows).

- made the internal help file generation use the same tcl2c scheme
  as the internal tcl file generation (since any compiler that can't
  handle one can't handle the other, e.g., Microsoft's VC4.x).

- made the output-characters-instead-of-strings mode of tcl2c be a -c
  flag rather than a compile time option.

- tried to simplify the makefiles by using suffix rules for the html
  to c & tcl to c conversions and by using VPATH to locate the files.
  (this required a bit of renaming to rationalize the html vs. ehtml
  names and file vs. array tcl names.)

- Bug fixes:
   - rearranged several error msg printers that did "fprintf" followed
     by 'perror' (the fprintf will wipe out errno).
   - got rid of some debugging 'puts' statements in start_media_tool.
   - fixed a few of the many gcc -Wall errors (ones that looked like
     they'd cause problems under windows or other architectures).
   - replace a very creative way of trying to turn a string into an
     ip address with a more mundane version that works.
   - rearranged the socket/bind/connect/setsockopt calls to follow the
     one and only sequence that windows will accept.
   - ran all the tcl code through tclCheck & tcl_cruncher to check
     brace, paren, quote, etc., matching.  This found a few errors
     that would have bitten someone under the right circumstances.
     (doing this required nuking some commented out, obsolete or debug
     code that fooled the checker).
   - fixed bug in tcl2c when CANDOBIGSTRINGS isn't defined -- wasn't
     adding null byte string terminator.
   - got rid of pointless bind to 0.0 in www recv code (it does nothing
     and microsoft gives an error when you do it).
   - made quit button do a 'write_cache' since doing it only when main
     window is destroyed can cause cache to not get written out.

2.2a11 31 May 96 fenner@parc.xerox.com

- Change iconbutton to raise the button before invoking command like the
  normal tk button, so that if you click on "more info" and then dismiss
  the window you don't get an error when the web page finishes
  loading.
- Delete the B2-Motion event to prevent accidental scrolling of the session
  windows.
- Attempt (it doesn't work for unknown reason) to bind j and k to scrolling
  up and down in the session windows like in sd.
- Make the session redisplay sort case-insensitive
- Attempt to add popups for more buttons in the "new" interface
  (but the popups need to learn about iconbuttons)
- Make web status "Parsing" while parsing the page, and "Finished" only
  after done parsing
- Make "Invalid Content Type" message reflect the actual content type
  instead of the data of the last header that was parsed
- Implement "#xxx" anchors (use catch instead of foreach?)
- Indent <dd> and center <center> (sometimes)
- Partially implement <META HTTP-EQUIV> for "poor man's redirect"
- Parse </br> as <br> since Netscape allows it
- Allow comments with <!--stuff , the old code required a space
- Add "parsestr" function to parse out KEY=value or KEY="va l u e" pairs
- Impement full RFC1866 list of character elements, including &#nnn;
- Implement non-blocking connect for webto, keyed on #define NBCONNECT
  so it can be conditionalized per platform
- Use ~/.RTPdefaults if it exists to guess name and email
- Fix bug in tech_new's decision about configuring name and email
 
- Fix "Illegal Scope Value, Scope value must be between 0 and 255" error
  if you don't click on any scope-related buttons and just create a session.
- New preferences scheme.  Each panel of the preferences menu
  has its own function, named "pref_XXX", which takes several
  possible arguments:
        copyin          copy from sdr's variables to prefs(XXX_variable)
        copyout         copy from prefs(XXX_variable) to sdr's variables
        defaults        set the prefs(XXX_variable) to default values
        create window width height
                        create the user interface using window as your
                        top level & make sure your widget matches the
                        width and height
        save file       output tcl commands to file to set the sdr
                        variables to their current values, e.g.
                        puts $file [list set webproxy $webproxy]
 
  One thing to potentially add is "verify", e.g. make sure all values
  are within their allowed range (like no empty phone numbers allowed)
- Added listening to the sd address, conditionalized on
  LISTEN_FOR_SD
- Fix typo; the ttl for the admin scope "site" is actually 15.
- Set ldata($aid,medianum) to 0 for sessions with no media.
  This was previously done in another section of the function
  but needs to be done in all cases.
- Add sdr_new_session_hook, which gets called whenever a new session
  is heard.  It may be in the wrong place.
- Fix confusion about exiting; if the ~/.sdr directory didn't exist then
  the cache directory wouldn't get created so the cache wouldn't get written.
- Fix UI weirdness in preferred session selection.  Two things:
  - The two listboxes could potentially scroll independently of each other.
  - Clicking on an entry near the bottom of the list can shorten the list,
    causing the listbox to scroll.  Fixed by adding the new value before
    deleting the old one.
- Change \r\n to \n only, and then change \r to \n to attempt to handle
  HTTP servers that return \r-seperated lines.  Also fixes the \r's
  at the end of <PRE> lines.
- Made anchors use "catch" instead of "foreach" to move to the mark
- Media setup bug in quick-call fixed.

2.2a10 16 May 96 mhandley
        Problem with backgrounded sdr writing startup messages fixed.
	Session display windows now disappear when the session times out.
	Xresources now work again (haven't been since the port to Tk4.0)
	pcm2/dvi2 now the default packetisation if a ptime attr is not
          specified (suggested by Van Jacobson)
	Bug preventing setting of midnight start times fixed.
	Bug preventing sdr starting sessions with several streams of the 
          same media fixed.
	Experimental code added to allow sdr to continue running after logout 
          and X display destruction ("-s" flag" specifies this)
2.2a9 9-12 May 96 mhandley
        Preferences user interface completely re-written to reduce
          complexity and number of windows required.
        Mechanism to specify preferered tools for each format added.
        UI Bug in specifying prefered sessions fixed.
        Can now copy from session information window into X cut buffer
          for phone numbers, addresses, etc.
        Cache files now get written on logout (failed X connection) as
          well as on hitting "quit" or announcing new sessions.
        A first attempt at sorting out keyboard (Tab) traversal of
          the user interface (as in Motif Compliance!)

	WWW browser patches from Bill Fenner:
	- The "display url" code tended to make the status "Finished" 
	  when it shouldn't be, so I started using a global variable to 
	  hold the status.
	- Parse and use "<BASE HREF=>" elements; our proxy server depends 
	  on this (e.g. if you ask our proxy server for 
	  ftp://ftp.parc.xerox.com/pub/net-research it puts in  
	  <BASE HREF="ftp://ftp.parc.xerox.com/pub/net-research/"> instead 
	  of sending a  redirect.

2.2a8 8 May 96 mhandley
        command line option "-d1" added to aid debugging of announcement
          problems.
        initialisation bug with ttl scoped sessions when new admin scope
          zones were defined is now fixed.
        initialisation bug in setting ttl for admin scoped sessions fixed.
        scrollbar now works again when specifying visible sessions in prefs.
2.2a7 4-6 May 96 mhandley
        Some parser checks that were missing added.
          - should prevent crashes with broken MCM sd announcements.
        Calendar interface redesigned to use pop-up fewer windows.
        Calendar now handles repeat times properly.
        Incoming invitations now force the popup of the invitation window
          on window managers like twm which nornally delay window placement.
        Minor changes to prevent sdr exiting in certain error conditions.
        long phone numbers bug fixed.
2.2a6 27 Apr 96 mhandley
        TkPlatformInit redefined to fix tk4.1b3 stupidity trying to
          explicitly load $TK_LIBRARY/tk.tcl
2.2a5 15-26 Apr 96 mhandley
        Basic SIP implementation added.
          allows users to invite other users to join advertised sessons
        Tcl SDP parsers added for SIP messages.
        Sensible error message now produced when DISPLAY is incorrect.
        better support for monochrome displays added
        plugin parser made more robust to odd spaces
        new session window made shorter and fatter
        moved cache files from .sdr dir to .sdr/cache dir.
        youremail variable added to plugin mechanism
        bug in plugin attr parser fixed (was preventing wb session launch)
        check added so sdr ignores announcements with later versions than 0
        repeat times now displayed properly in session display window
        window placement code improved - windows should get moved less
        added code to parse mailto URLs (but not to handle them yet)
        bug displaying sessions with no media fixed.
        bugs in recording startup fixed by Bill Fenner
2.2a4 15 Apr 96 mhandley
        macro/value pairs added to plugin mechanism
        vat protocol id's added back to vat startup script
        TCL bug in SunOS4 startup config worked around
2.2a3 15 Apr 96 mhandley
        stupid bugs in a2 fixed
2.2a2 12-13 Apr 96 mhandley
        plugin attributes now finished
        first pass at built-in "plugin" config files
        plugin help pages completed
        many little changes to WWW browser to improve appearance of help pages
        moved all platforms to tk4.1/tcl7.5
        some low-priority status messages now appear on sdr main 
          window rather than annoying little popups.
2.2a1 9-10 Apr 96 mhandley
        times with leading zeros bug fixed.
        really fixed(!): double clicking in main window produced a tcl error
        unknown media types now handled gracefully.
        bugs introduced with spec changes fixed.
        startup code for tools moved to separate modules and
          re-written to use plug-in config files to make configuration
            much more flexible and simpler.
          .sdr.tcl no longer used to configure session startup
        plugins used to configure menus when creating and editing sessions
        plugins used for fmt/proto name mapping in session listings
        response improved whilst writing cache file
        rtp mapping code from 2.2a0 removed
2.2a0 3 Apr 96 mhandley (telnet from California)
        Octal problem with changing date fixed but not tested.
        protocol fixes to support current SDP spec added.
2.1a12 30 Jan 96 mhandley
        fixed: double clicking in main window produced a tcl error
        ptime attribute added for audio and code to start up {pcm,dvi}{2,4}
        added.
        tearoffs removed from pull-right media attribute menus
2.1a11 26 Jan 96 mhandley
        Fixed bug in storing addresses for address allocation

       25 Jan 96 fenner@parc.xerox.com
        FreeBSD port done.
        strerror() added to compat.c
        Union in a struct in_addr replaced with bit manipulation for
        4.4 BSD compatibility
        Added the ability to use a proxy server and a preference to go
        with it, and made the WWW browser error messages slightly nicer.
        Added (not-quite-fully-compliant-but-99%) HTML comment parsing, and
        got rid of an infinite loop that occurred on pages with bare &'s (see
        http://town.hall.org/).

       24 Jan 96 mhandley
        Lots of restructuring as a result of work on the sdr_server.

2.1a10 13 Jan 96 mhandley
        Simple interface added for session creation by less techincal users
        Simple interface added for session display
        Stupid timing hole resulting in session duplication while
        editing sessions now fixed.
        Default audio protocol changed to be RTP rather than VAT protocol
        Lots of restructuring in code to create new sessions.
        A little restructuring in session display code - now more robust to
        sessions being modified.
        .sdr_cache is now obsolete, and is replaced by the .sdr directory
          - this makes storing encrypted sessions cleaner
          - this also prevents incorrect editing of one session's cache entry
            corrupting others
        old .sdr_cache files get read (once) and then deleted.
        Calendar daily entries are now hot (popup the relevant session).
        Calendar daily entries now only get an arrowhead if they start or 
        finish on that day.
        Hot entries now get highlighted on entry (in all windows).
        Clicking on an already raised session in sdr main window now dismisses
        it - this makes it easier to browse sessions.
        WWW browser and help system now handle HTML escaped special chars
        WWW browser bug displaying HTML after last tag fixed
        WWW browser handing of Relative URLs from redirected pages now fixed.
2.1a9 9 Jan 96 mhandley
        Session Timeout timer-handler moved to start of session timeout code
        to improve robustness
        TCL session state time values were not all correctly set up for
        infinitely long sessions - now fixed.
        Session deletion code made more robust.
        Spurious error message with length 0 sdr_cache file fixed.
2.1a8 6 Dec 95 mhandley
        Stupid bug dealing with ad id comparisons fixed        
2.1a7 2 Dec 95 mhandley
        middle-button on empty session window error fixed.
        incorrect port bug when starting nv fixed
        some spurious debugging messages disabled
        tearoffs removed from menus (shouldn't have been there in the first
        place)
2.1a6 1 Dec 95 mhandley
        tk4.0 porting bug related to editing repeated sessions fixed
        spurious incorrect error messages removed.
        ballon help initial state was inconsistent with UI - now fixed.
        text-wrap problem is session popups fixed.
        calendar bug with times before 1am fixed
        editing sessions didn't clear previous text media - now fixed.
        tk4.0 porting bug in WWW browser image link code fixed.
        browser history list is now cleared on dismissing the window
         - thanks to Bill Fenner for reporting all these!
        BUGS and CHANGES now included in help pages.
2.1a5 30 Nov 95 mhandley
        Released sdr with sd compat timestamps rather than NTP timestamps
         - now fixed!
        sscanf problem in parser on HPUX fixed - thanks to Piers O'Hanlon
        session-id and session-versions fields were swapped - now fixed
        spurious error message when parsing indefinite sessions removed
2.1a4 28 Nov 95 mhandley
        TK_LIBRARY dependency had found its was back in with tk4.0 
        - removed again
        Paste to description box tk4.0 bug fixed
        Editing of ttl scoped sessions reset ttl - now fixed
        Stupid calendar month wrapping bug fixed
2.1a3 27 Nov 95 mhandley
        small changes related to porting to other platforms
2.1a2 25 Nov 95 mhandley
        Vat and vic default program names fixed
        Media labels in "new" window fixed
        Sdr.tcl split in two and cleaned up slightly
        Error checking improved in config files
        "new" window disabled "protocol" and "fmt" menus fixed
        setmediamode re-written
        UK scope shouldn't have been in as a default!
        Help pages greatly extended
        "Bugs" and "Changes" now automatically included in help system
        Debugging turned off by default
2.1a1 24 Nov 95 mhandley
        Ported to Tk4.0 - loads of stuff changed
        Protocol updated to draft-ietf-mmusic-sdp-01 subset
        IconButton re-written to work with tk4.0
        Horrible workaround added to prevent clash between iconbutton functions
          and widgets with same names (used to work in tk3.6)
        BalloonHelp modified to work with tk4.0
        Some new balloons added - more are needed
        WWW browser modified to work with tk4.0
        More preferences options added + preferences re-written somewhat
        Colour changed
        Vat and vic startup scripts totally re-written - now supports
         conf control channel for voice switching
        Tool to start for nv, ivs, and rtp audio now a preference selection.
        Allocates even ports for rtp
        Allocates prividged ports according to mrouted 3.6 rate limiter
        "new" protocol menu fixed
        Loads and loads of little things to do with tk4.0
2.0a10 17 Aug 95 mhandley
        stupid tcl bug with dates with leading zeros fixed
2.0a9 13 Jul 95 mhandley
        administrative scoping now works on multiple addresses/ports
2.0a8 12 Jul 95 mhandley
        administrative scoping added to interface - currently hardwired scopes
        but address dependant on scope working
2.0a7 12 Jul 95 mhandley
        nt added start_whiteboard procedure
        multiple multicast addresses were broken in parser by additional 
        strlen check in a4 - now fixed
2.0a6 11 Jul 95 mhandley
        Bugs fixed:
        Now handles main window being slightly offscreen (-ve geometries)
        Dhild windows now get moved completely onscreen (I hate TK sometimes!)
        Bug in session deletion fixed - sessions weren't getting deleted 
        permanently.
        Bug in www browser fixed - now handles any sized file
        Session deletion/selection with empty main window now doesnt
        cause an error
2.0a5 10 Jul 95 mhandley
        Corrected non-conformance with SDPv2 draft-01
        Transport protocol field added to "m=" fields
         - not compatible with previous versions!
2.0a4 4 Jul 95 mhandley
        First released version conforming to SDPv2 draft-01
2.0a3 20 Jun 95 mhandley
        too many changes to list!
        Handles most SDPv2 times and repeat times
        Handles SDPv2 fmt fields
2.0a2 19 May 95 mhandley
        built in WWW browser added to sdr
1.2a11 10 Mar 95 mhandley
        Recording functionality added
        Bug in day calendar popup fixed
1.2a10 2 Mar 95 mhandley
        Language internationalisation completed.  Now reads ~/.sdr.${LANG}
        file for internationalisation code.
1.2a9  1 Mar 95, mhandley
        Fixed bug in calendar - times before 10am didn't work!
        Language internationalisation partially added.
1.2a8, 28 Feb 95, mhandley
        Calendar label problem with German language labels fixed.
        Calendar day numbering problem with month 2 and month 3 fixed
        "unknown command .desc?.f.f0.desc" error fixed.
The sdr Session Directory:

The sdr Session Directory:

An Mbone Conference Scheduling and Booking System

Mark Handley
Department of Computer Science
University College London
Draft 1.1, 14th April 1996

Sdr is a Session Directory designed for announcing and scheduling multimedia conferences on the Mbone - the multicast backbone of the Internet. Sdr is loosely modelled on sd - LBL's Mbone Session Directory. Sdr extends the sd model in a number of ways, particularly in the degree of detail about the timing and resources required by a conference, and in the provision of a much more flexible interface for querying the existence of sessions or of any sessions that may potentially clash with a new session.


The Session Announcement Model

The Session Announcement Model

Sdr uses an announcement protocol called the Session Directory Announcement Protocol. In its simplest form, this involved periodically multicasting a session announcement packet describing a particular session. To receive SDAP, a receiver simply listens on a well known multicast address and port. Sessions are described using the Session Description Protocol (described below). If a receiver receives a session announcement packet it simply decodes the SDP message, and then can display the session information for the user. The interval between repeats of the same session description message depends on the number of sessions being announced (each sender at a particular scope can hear the other senders in the same scope) such that the bandwidth being used for session announcements of a particular scope is kept approximately constant.

If a receiver has been listening for a set time, and fails to hear a session announcement, then the receiver can conclude that the session has been deleted and no longer exists. The set period is based on the receivers estimate of how often the sender should be sending, and is (arbitrarily) set to ten times the estimated send period. It is possible for network partitions to force inadvertent deletion of sessions, but inadvertent deletion due to packet loss is extremely unlikely. In any event, such a deleted session will be reinstated as soon as the network partition is resolved and another announcement packet is received.

To allow relatively quick startup and display of long-lived sessions, sdr keeps a local (per user) cache of sessions. Upon startup, sdr reads this cache, and displays those which have not yet reached their expiry time. This cache also holds sessions created by its owner, and upon sdr startup, these sessions start to be re-announced. Note that with this simple model, a user must have a copy of sdr running for a session created by that user to be announced and to not time-out at receivers.

Extensions to SDAP not currently implemented involve allowing other local copies of sdr to make proxy announcements of a session when its originator is not announcing it. Also other copies of sdr can serve as cache servers, so that upon startup, a copy of sdr queries any other locally running copies of sdr to update the entries in its local cache. This can be extended by having an sdr daemon running continuously at a site and performing both the proxy announcement and proxy receiver tasks - however the daemon is not essential for sdr to be used - it simply provides an improvement is performance.

The Session Description Protocol

The Session Description Protocol

The Session Description Protocol (SDP) is an ASCII text based protocol for describing multimedia sessions and their related scheduling information. It was originally based on the protocol used by the sd session directory from Lawrence Berkeley Labs, but has been extended and generalised significantly since then.

The purpose of SDP is to convey information about media streams in multimedia sessions to allow the recipients of a session description to participate in the session. SDP is primarily intended for use in a internetwork, although it is sufficiently general that it can describe conferences in other network environments.

A multimedia session, for these purposes, is defined as a set of media streams that exist for a duration of time. Media streams can be many-to-many. The times during which the session is active need not be continuous.

Multicast based sessions on the internet differ from many other forms of conferencing in that anyone receiving the traffic can join the session (unless the session traffic is encrypted). In such an environment, SDP serves two primary purposes - as a means to communicate the existence and timing of a session, and as a means to convey sufficient information to enable joining and participating in the session. In a unicast environment, only the latter purpose is likely to be relevant.

Thus the information SDP must convey includes:

  • Name and purpose of session
  • Time(s) the session is active
  • The media comprising the session
  • Information to receive those media

Scheduling Sessions

Scheduling Sessions

New sessions can be created by pressing the ``New" button on the sdr main window. Every session must have a name, a short description, a scope, contact information, a start time and a stop time. In addition, sessions may optionally also possess links to further information in the world wide web, a number of detailed media descriptions, and more detailed timing information.


Links to the World Wide Web

Links to the World Wide Web

A session announcement can contain an Uniform Resource Locator (URL) as a link to related information in the world wide web. The preferences menu determines how sdr follows such references - three options are supported:

  • Using the simple built in WWW browser
  • Starting an external browser such as netscape or Mosaic
  • Directing an already running external browser to the URL (Mosaic and netscape permit this sort of remote control operation).
If you have an colour display of depth 8 bits, using the built in browser is recommended as external browsers use a significant number of the 256 available colours, leaving you with few colours remaining for any tools you wish to use in a multimedia conference. If you have a 24bit display, external browsers are likely to provide you with better performance and prettier displays than the built-in browser. When creating a session, it is recommended that the URL be tested (using the Test button) as typing mistakes here will make the URL useless. Media Descriptions

Media Descriptions

Media descriptions are the main reason for describing a session, as they allow the receiver of an announcement to start the correct media tools directly from sdr with all the correct flags and settings to join the conference. Sdr allows you to create conferences with up to one media tool of each of the following types:

  • audio
  • video
  • whiteboard (including shared editors)
  • text
In fact sdr can receive and start sessions with more than one of each media, but the standard interface does not permit the creation of such sessions in an effort to make the session creation interface simpler to use. To include a media in your session, select the media by clicking on the left ``X" button When a media is selected, a default media format will be selected, along with default addresses, transport protocol and ports. The media format and transport protocol can be changed using the relevant pull down menus. The address and port are allocated in such a way that they should avoid clashes with other scheduled sessions - the addresses sdr provides should normally be used, although user specified ones can be substituted if required. In particular, ports are chosen such that rate-limiting in Mbone routers will preferentially forward audio rather than video when a multicast tunnel is congested. If everyone you expect to participate in your session is likely to wish to receive all the media you have selected, then using one multicast address for all your media is appropriate. If some receivers are likely to not wish to receive some media - for example some sites have insufficient bandwidth to receive video - then selecting one multicast address per media is appropriate as this permits unwanted traffic to be pruned back from these low bandwidth participant sites. Detailed Timing

Detailed Timing

If your session is not going to be active continuously between its start and stop times, then this detailed timing information should be provided so that users that wish to participate know the precise times, and users that do not wish to participate can know when to expect your traffic to be active.

Sdr allows you to specify up to three active times or repeat intervals for your session - each active time or repeat interval specifies an addition set of times when the session will be active. The limit of three is not imposed by the protocol - if sdr receives an announcement with more than three repeat times it can decode and display it - but rather to simplify the user interface for session creation. Administrative and TTL Scope

Administrative and TTL Scope

The multicast backbone provides two methods by which the sites able to receive traffic can be constrained - TTL scope and administrative scope.


TTL Scope

TTL Scope

TTL Scope is constrained by the ``Time To Live" (TTL) field in the IP packets a multicast application sends. An application sends its data with a fixed TTL. Each multicast router that the data traverses decreases the TTL on the packets by one. Each multicast router also has a threshold associated with each multicast capable interface or multicast tunnel. If the TTL on the data packets arriving at a router is lower that the threshold of the interface or tunnel, then the packet is not forwarded out of that interface.

The multicast tunnels comprising the Mbone are configured so that it is possible to constrain a conference to a particular region of the Mbone by careful setting of the TTL. Thus the multicast tunnels in Europe are generally configured with the following thresholds:

  • Low Speed Tunnels: 128
  • Intercontinental: 64
  • International (within Europe): 48
  • Between institutions: 16-32 depending on the links involved
  • Within an institution: 1-16
Thus if I'm sending from the UK, and want my traffic to reach Europe only, I would send with a TTL of 63, which would traverse the international tunnels but not the intercontinental ones. Administrative Scope

Administrative Scope

Administrative Scope uses different ranges of multicast addresses to constrain multicast traffic to a particular region. To configure an administrative scope zone, all the multicast routers bordering that zone must be configured to be a boundary to that zone for a range of multicast addresses. Unlike TTL scope, if a conference is on a scoped multicast address, traffic sources outside the scope zone will not be able to inject traffic into the conference as administrative scope zone boundaries are bi-directional. A particular scope zone has a range of multicast addresses, a default TTL, and a name. Users of administrative scope zones only need to know the zone name (e.g. ``United Kingdom'') to be able to scope their conference correctly - the TTL and the address are allocated by sdr.

Currently there is no automatic way for sdr to learn about the relevant scope zones - this must be configured on a per-site basis. Bandwidth Allocation

Bandwidth Allocation

Each scope range (whether TTL scoped or administratively scoped) has a recommended maximum bandwidth associated with it. This is the maximum bandwidth a session should use at that scope. Most of the Mbone is currently configured for only a small number of concurrent sessions, (although this is likely to change as the Mbone is increasingly provided using native multicast in routers rather than an overlay of multicast tunnels). For this reason it is important to be able to see if a session I wish to schedule will clash with other sessions already scheduled, and to automatically set the maximum bandwidth of the tools to comprise my session.

Unfortunately many users do not know sufficient about the network to be able to decide on appropriate bandwidth figures for their session. To get around this, sdr allows users to specify their sessions as ``meetings'' or as ``broadcasts'', and lets the audio and video rates be set as ``low'', ``normal'' and ``other'', where ``other'' requires that a bandwidth value be inserted. ``meetings'' also allow the user to specify ``number of simultaneous video streams''. Sdr users this information to set fields indicating the total bandwidth of the conference and the bandwidth to be used by each tool in the conference.

If a user attempts to schedule a session that will exceed the recommended available bandwidth for that scope (based on what other sessions are scheduled) then it will issue a warning and indicate which other session the new session will clash with. Secure Announcements

Secure Announcements

Although the purpose of sdr is to advertise sessions, not all sessions should be advertised publicly. However, it is important that even secret sessions use the same announcement mechanism, so that their bandwidth usage can be taken into account, and so that their multicast addresses are not inadvertently re-used. Thus Sdr permits secure sessions to be advertised, by announcing them twice - once unencrypted with just the bandwidth, contact info and multicast addresses, and once encrypted with all of the information including encryption keys for the media tools. Secure sessions do not appear in Sdr's listing of sessions unless the correct encryption key has been inserted.

Sdr allows a session to be created as ``public'' or ``private''. To create a private session, sdr must have been pre-configured with a set of private group names and their encryption keys. Normally this keys will have been exchanged using privacy enhanced electronic mail. When the user selects ``private'', the list of the groups the user has keys for is displayed, and the user can select a group. The encryption keys for these groups are not displayed on the interface at any time, and they are themselves stored encrypted in a file. Thus if a user wants sdr to receive or send encrypted sessions, they must enter a password to sdr to allow it to decrypt this key file. Receiving Announcements

Receiving Announcements

When announcements are received, they are displayed in Sdr's main window. Sdr has four modes which decide which of the currently advertised sessions are shown:

  • All Session - all the sessions received are displayed.
  • Prefered Sessions - display all the sessions except those the user has stated they're not interested in.
  • Current Sessions - display only those sessions that are currently active (including those that are permanently active)
  • Future Sessions - display only those sessions that are not currently active.

The default is Prefered Sessions, and the other options can be selected from the Preferences window. In this mode, clicking the right mouse button on a session will hide the session. A menu is available from the Preferences menu which allows the user to see all session, prefered or not, and select which are to be shown and which are to be hidden.

Clicking the left mouse button on the name of a session in the Sdr main window will pop-up a window describing the session - an example is shown in figures 3 and 4. This lists a description of the session, when it is active, contact information for the creator of the session, and the media the session comprises. Clicking on ``Start All" will start all of the media tools necessary to join the session. The media tools can also be started individually - this can be useful for restarting a tool that has failed, or for starting some tools on one machine and some on another as is common in a conference room scenario.

If the session was created by this user, then ``edit" and ``delete" options are also available. A ``record" option is also available, which will operate an interface to one of several session recording tools. This recording interface is not yet implemented. The Calendar

The Calendar

Sdr provides a second way to view sessions in addition to their display in the main window - selecting Calendar from the Sdr main window pops up a calendar view of the current month and the next two months (see figure 6). Days on which there are sessions scheduled are highlighted in blue. Clicking on a day on which there is a session scheduled expands that day to show which sessions are planned and what times they will be active (see figure 7). This allows potential future clashes to be spotted and negotiation entered into about suitable use of available bandwidth. The Web Browser

The Web Browser

Sdr has a simple built-in World Wide Web browser. This is not intended to be a full functioned browser because its main purpose is to allow references to information about sessions to be checked and browsed without starting up a fully functioned WWW browser which would use a significant proportion of the available colour table entries on most machines with 8 bit displays. Thus Sdr's built in browser does not display inline or background images - it merely displays the formatted HTML text of a page with the hyperlinks to other pages highlighted in blue. Clicking on a blue link will take you to that page. Clicking on backward will take you back to the previous page, and clicking on ``forward'' wil take you forward to the page you just came backwards from. A URL can be typed directly into the entry box at the bottom of the window if required, and the browser will then go directly to that page. The World Wide Web is really beyond the scope of this note - for more details see [2]. References


References

1
M. Handley, V. Jacobson, ``SDP: Session Description Protocol'' INTERNET DRAFT, Nov 1995.
2
M. Handley, J. Crowcroft, ``The World Wide Web: Beneath the Surf'' UCL Press, London, 1995, ISBN 1-85728-435-6.

Sdr Plug-In Modules

Sdr Plug-In Modules

Sdr can be configured to support new tools by means of plug-in modules which define the media, protocol and formats supported by a tool, along with long-form names for these formats and the flags that are needed to start up the tool.

Sdr will read files in "/usr/local/etc/sdr/plugins" and "~/.sdr/plugins" and will search for files whose name begins "sdr2.plugin.". The naming convention for plugins is "sdr2.plugin.sequence.media.protocol.format.tool" where for convenience, format is often wildcarded when the plugin file contains many formats.

New media can also defined in this manner but this should not be done without prior discussion on the mailing list "remconf@es.net" to avoid undesirable proliferation of media definitions for what really should be protocols or formats.

Sdr has built in definitions for the following:

  • audio rtp pcm vat
  • audio rtp dvi vat
  • audio rtp gsm vat
  • audio rtp lpc vat
  • audio vat pcm vat
  • audio vat dvi vat
  • audio vat gsm vat
  • audio vat lpc vat
  • audio rtp pcm rat
  • audio rtp dvi rat
  • audio rtp gsm rat
  • audio rtp lpc rat
  • video rtp h261 vic
  • video rtp nv vic
  • video rtp jpeg vic
  • video rtp cellB vic
  • video rtp nv nv
  • whiteboard udp wb wb
  • text udp nt nt
If you wish to add new protocols,formats or tools you'll need to create an appropriate sdr plugin and distribute it to anyone you wish to participate in your session.

Further information

For further information on plugins, see: Writing sdr plugins

Writing sdr plugins

Sdr plug-in configuration files follow a strict format of grouped attribute:value pairs with one attribute value pair per line. Leading whitespace is ignored. Whitespace in the value part of an attribute:value pair is significant.

Compulsory fields

For a format or tool definition file, the following attributes are compulsory and should be in the following order:
  media:media
  proto:protocol
  tool:tool-name
See the SDP specification for definitions of media and protocol. Tool-name is the name of the tool you wish to be started to send/receive this session.

Optional header fields

protoname

As the protocol will often not be very meaning full to humans, these may be followed by further definition:
  protoname:human readable versions of protocol
Protoname is used at configure menus and labels on the user interface.

create

Most plugins define media and formats that you wish to be able to announce. However, some may be just for backwards compatibility so you can receive them but do not wish to announce them. If this is the case, you can use the create field to specify that you don't wish this plugin to contribute to the session creation menus and options:
  create:no

Format definitions

After these definitions should come one or more format definitions. The minimal form of a format definition is:
  fmt:format
See the SDP specification for a more complete definition of what is meant by a format.

More normally however a format definition will require additional configuration, and this can be done as follows:

  fmt:format
  {
      fmtname:human readable version of format
      flags:command line flags for tool with this format
  }

Media Attributes

Both media and session definitions can contain optional attributes. These can be configured in the plugin on a per-tool or a per-format basis.

Attributes can be of two types - either with a set of values, or just on/off.

On-off attributes can be configured as follows:

  attr:attribute name
  {
      attrname:human readable version of attribute
      flags:command line flags for tool with this attribute
  }
Attributes with a set of values can be configured as follows:
  attr:attribute name
  {
      attrname:human readable version of attribute
      attrvalue:one possible value of attribute
      {
         attrvaluename:human readable version of this attribute vale
         flags:command line flags for tool with this attribute and value
      }
      attrvalue:another possible value of attribute
      {
         attrvaluename:human readable version of this attribute vale
         flags:command line flags for tool with this attribute and value
      }
  }
Either type of attribute may be used within a format definition (if the attribute is format specific) or after all the format definitions are complete (if the attribute is independant of the format).

This mechanism assumes you can explicitly list all the values of an attribute. Whilst this is often the case, it is not always so, and sdr plugins also allow the use of the macro and value definitions to allow flexible passing of attribute values directly to the media tool. See below for more details.

noattr

Occasionally you want to specify a behaviour to apply when an attribute is not present. To do this you use the noattr definition as follows:
  noattr:attribute name
  {
      flags:command line flags for tool if this attribute is missing
  }
A noattr definition must follow the equivalent attr definition.

Flags and Variables

The flags definition specifies a section of the command line that will be used to start the media tool if this plugin is matched. It can be used in attribute and format definitions and also after all the definitions are complete to finish the command line. A simple example is:
  media:audio
  proto:RTP/AVP
  tool:rat
  fmt:pcm
  {
    flags:-f pcm
  }
  fmt:dvi
  {
    flags:-f dvi
  }
  flags:-t $(TTL)
  flags:$(ADDRESS)/$(PORT)

For an rtp session with pcm format audio on address 224.2.3.4 and port 3456 with ttl 1, this would start the rat tool as follows:

  rat -f pcm -t 1 224.2.3.4/3456
As can be seen above, flags definitions can include variables that will be expanded when the session is started. As complete list of these variables is:
  • $(ADDRESS) - the address to send/recv to
  • $(PORT) - the transport port to send/recv on
  • $(TTL) - the ttl for multicast sessions
  • $(PROTO) - the value of the protocol field
  • $(FMT) - the value of the format field
  • $(SESSNAME) - the name of the session
  • $(CHAN) - the channel number for LBL's conference bus
  • $(YOUREMAIL) - the email address of the person running sdr

Macros

In cases where the value of an attribute must be passed directly to the media tool, the above mechanisms are sometimes not sufficient. To make this mechanism more flexible, sdr plugins provide a very simple macro facility. An example is:
media:audio
proto:vat
tool:vat
fmt:pcm
attr:id
{
  macro:ID
  {
    value:/$(VALUE)
  }
}
flags:$(ADDRESS)/$(PORT)$(ID)
In this case, the session attribute attribute "id" needs to be passed to vat at the end of the command line. The special variable $(VALUE) is given the value of the "id" attribute, and this is substitutes in the string given in the "value" definition. The resulting string is stored in the $(ID) variable, and expanded in the same way normal variables are when the tool is run. If there is no "id" attribute in this particular session, then the $(ID) variable is set to the empty string.

For example, a session with address/port 224.5.6.7/5432 and no id field would be started as:

vat 224.5.6.7/5432
and a session with the id atribute 1244 would have $(ID) defined as "/1234" and would be started as:
vat 224.5.6.7/5432/1234
$X`#TLdT,LрX

About Sdr

Sdr is a session directory tool designed to allow the advertisement and joining of multicast conferences on the
Mbone. It was originally based on sd written by Van Jacobson at LBNL, but implements a later version of the session description protocol than sd does. Sd and sdr are not compatible. Help is available on the following topics:

bugs and changes

Sdr was written by Mark Handley at UCL as part of the MICE and MERCI projects. Significant additions and modifications have been made by Bill Fenner at Xerox PARC and by Van Jacobson at LBNLsip recv errorWarning: 2K announcement truncated sip_advertsip_user_alert $sip_advert %s puts $errorInfocouldn't get SIP socketconnectDest Address problem SO_REUSEADDRttl: %d setsockopt ttlsend: %d: res_mkqueryres_sendTO=SIP/1.0 REQSIP/1.0 REP1 2 3 4 Illegal SIP reply type sip_success ""sip_failure "RINGINGsip_status "couldn't get SIP receive socketbindAddress: %x, Port: %d setsockopt - IP_ADD_MEMBERSHIPtk_library.%d%s0-1okdupclock format [clock seconds] -format %wclock format [clock scan {%d day}] -format %%aclock format [clock scan {%d day}] -format %%Aclock scan 1/1clock format [clock scan {%d month} -base %u] -format %%hclock format [clock scan {%d month} -base %u] -format %%B-short%s@%strusted1{%s} %usdrUse synchronous mode for display server-syncName to use for application-nameDisplay to use-displayInitial geometry for window-geometryFile from which to read commands-file%s envDISPLAY-name sdr argvSdr: %s ui_generate_portgenerate_idui_generate_addressgetemailaddresscreatesessioncheckaddressgethostaddrgetusernameui_stop_session_adgetdaynamegetmonnamewebtosave_www_data_to_filestop_www_loadingsd_listenlookup_hostsip_send_msgui_quitset_passphraseget_passphraseadd_keydelete_keyfind_key_by_nameload_keyssave_keyswrite_crypted_filesdr:%s %s puts $errorInfotkerror {}tcl_libswm geometry . setting geometrytcl_generictcl_wwwtcl_sap_crypttcl_newtcl_start_toolstcl_parsed_pluginstcl_pluginstcl_siptcl_sdptcl_sdrContent-Type: text/html usage: webto url [proxy] [argc=%d] Parse error in URL: %s Content-Type: text/html Parse error in URL helpContent-Type: text/html http/Content-Type: text/html

Unknown Host

%s does not existwebstatusConnecting...socketconnectgetsockoptGET %s HTTP/1.0 Accept: text/plain Accept: text/html Accept: image/* Receiving...updateshow_activeftpmsgpopupProtocol ErrorSorry - this browser does not yet support ftp URLsmailtoSorry - this browser does not yet support mailto URLsUnknown protocolContent-Type: text/html

Error

%s: Unknown error %d Content-Type: text/html

Error

%s: %s w/keysenter_passphrasepre-encr len: %d post-encr len: %d keyid: %x timeout: %x setting key: %s ..done pre-decrypt len: %d post-decrypt len: %d %d, v=resource sdrHomeDuplicate Key Register attempt: %s install_key ""install_key.tmpwr%s: errno %d - %s qfDES_malloc???qfDES_realloc()%02xqfDES_copy()# init.tcl -- # # Default system startup file for Tcl-based applications. Defines # "unknown" procedure and auto-load facilities. # # SCCS: @(#) init.tcl 1.54 96/04/21 13:55:08 # # Copyright (c) 1991-1993 The Regents of the University of California. # Copyright (c) 1994-1996 Sun Microsystems, Inc. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # if {[info commands package] == ""} { error "version mismatch: library\nscripts expect Tcl version 7.5b1 or later but the loaded version is\nonly [info patchlevel]" } package require -exact Tcl 7.5 if [catch {set auto_path $env(TCLLIBPATH)}] { set auto_path "" } if {[lsearch -exact $auto_path [info library]] < 0} { lappend auto_path [info library] } package unknown tclPkgUnknown if {[info commands exec] == ""} { # Some machines, such as the Macintosh, do not have exec set auto_noexec 1 } set errorCode "" set errorInfo "" # unknown -- # This procedure is called when a Tcl command is invoked that doesn't # exist in the interpreter. It takes the following steps to make the # command available: # # 1. See if the autoload facility can locate the command in a # Tcl script file. If so, load it and execute it. # 2. If the command was invoked interactively at top-level: # (a) see if the command exists as an executable UNIX program. # If so, "exec" the command. # (b) see if the command requests csh-like history substitution # in one of the common forms !!, !, or ^old^new. If # so, emulate csh's history substitution. # (c) see if the command is a unique abbreviation for another # command. If so, invoke the command. # # Arguments: # args - A list whose elements are the words of the original # command, including the command name. proc unknown args { global auto_noexec auto_noload env unknown_pending tcl_interactive global errorCode errorInfo # Save the values of errorCode and errorInfo variables, since they # may get modified if caught errors occur below. The variables will # be restored just before re-executing the missing command. set savedErrorCode $errorCode set savedErrorInfo $errorInfo set name [lindex $args 0] if ![info exists auto_noload] { # # Make sure we're not trying to load the same proc twice. # if [info exists unknown_pending($name)] { unset unknown_pending($name) if {[array size unknown_pending] == 0} { unset unknown_pending } return -code error "self-referential recursion in \"unknown\" for command \"$name\""; } set unknown_pending($name) pending; set ret [catch {auto_load $name} msg] unset unknown_pending($name); if {$ret != 0} { return -code $ret -errorcode $errorCode \ "error while autoloading \"$name\": $msg" } if ![array size unknown_pending] { unset unknown_pending } if $msg { set errorCode $savedErrorCode set errorInfo $savedErrorInfo set code [catch {uplevel $args} msg] if {$code == 1} { # # Strip the last five lines off the error stack (they're # from the "uplevel" command). # set new [split $errorInfo \n] set new [join [lrange $new 0 [expr [llength $new] - 6]] \n] return -code error -errorcode $errorCode \ -errorinfo $new $msg } else { return -code $code $msg } } } if {([info level] == 1) && ([info script] == "") \ && [info exists tcl_interactive] && $tcl_interactive} { if ![info exists auto_noexec] { if [auto_execok $name] { set errorCode $savedErrorCode set errorInfo $savedErrorInfo return [uplevel exec >&@stdout <@stdin $args] } } set errorCode $savedErrorCode set errorInfo $savedErrorInfo if {$name == "!!"} { return [uplevel {history redo}] } if [regexp {^!(.+)$} $name dummy event] { return [uplevel [list history redo $event]] } if [regexp {^\^([^^]*)\^([^^]*)\^?$} $name dummy old new] { return [uplevel [list history substitute $old $new]] } set cmds [info commands $name*] if {[llength $cmds] == 1} { return [uplevel [lreplace $args 0 0 $cmds]] } if {[llength $cmds] != 0} { if {$name == ""} { return -code error "empty command name \"\"" } else { return -code error \ "ambiguous command name \"$name\": [lsort $cmds]" } } } return -code error "invalid command name \"$name\"" } # auto_load -- # Checks a collection of library directories to see if a procedure # is defined in one of them. If so, it sources the appropriate # library file to create the procedure. Returns 1 if it successfully # loaded the procedure, 0 otherwise. # # Arguments: # cmd - Name of the command to find and load. proc auto_load cmd { global auto_index auto_oldpath auto_path env errorInfo errorCode if [info exists auto_index($cmd)] { uplevel #0 $auto_index($cmd) return [expr {[info commands $cmd] != ""}] } if ![info exists auto_path] { return 0 } if [info exists auto_oldpath] { if {$auto_oldpath == $auto_path} { return 0 } } set auto_oldpath $auto_path for {set i [expr [llength $auto_path] - 1]} {$i >= 0} {incr i -1} { set dir [lindex $auto_path $i] set f "" if [catch {set f [open [file join $dir tclIndex]]}] { continue } set error [catch { set id [gets $f] if {$id == "# Tcl autoload index file, version 2.0"} { eval [read $f] } elseif {$id == "# Tcl autoload index file: each line identifies a Tcl"} { while {[gets $f line] >= 0} { if {([string index $line 0] == "#") || ([llength $line] != 2)} { continue } set name [lindex $line 0] set auto_index($name) \ "source [file join $dir [lindex $line 1]]" } } else { error "[file join $dir tclIndex] isn't a proper Tcl index file" } } msg] if {$f != ""} { close $f } if $error { error $msg $errorInfo $errorCode } } if [info exists auto_index($cmd)] { uplevel #0 $auto_index($cmd) if {[info commands $cmd] != ""} { return 1 } } return 0 } if {[string compare $tcl_platform(platform) windows] == 0} { # auto_execok -- # # Returns 1 if there's an executable in the current path for the # given name, 0 otherwise. Builds an associative array auto_execs # that caches information about previous checks, for speed. # # Arguments: # name - Name of a command. # Windows version. # # Note that info executable doesn't work under Windows, so we have to # look for files with .exe, .com, or .bat extensions. Also, the path # may be in the Path or PATH environment variables, and path # components are separated with semicolons, not colons as under Unix. # proc auto_execok name { global auto_execs env if [info exists auto_execs($name)] { return $auto_execs($name) } set auto_execs($name) 0 if {[file pathtype $name] != "relative"} { foreach ext {.exe .bat .cmd} { if {[file exists ${name}${ext}] && ![file isdirectory ${name}${ext}]} { set auto_execs($name) 1 } } return $auto_execs($name) } if {! [info exists env(PATH)]} { if [info exists env(Path)] { set path $env(Path) } else { return 0 } } else { set path $env(PATH) } foreach dir [split $path {;}] { if {$dir == ""} { set dir . } foreach ext {.exe .bat .cmd} { set file [file join $dir ${name}${ext}] if {[file exists $file] && ![file isdirectory $file]} { set auto_execs($name) 1 return 1 } } } return 0 } } else { # Unix version. # proc auto_execok name { global auto_execs env if [info exists auto_execs($name)] { return $auto_execs($name) } set auto_execs($name) 0 if {[file pathtype $name] != "relative"} { if {[file executable $name] && ![file isdirectory $name]} { set auto_execs($name) 1 } return $auto_execs($name) } foreach dir [split $env(PATH) :] { if {$dir == ""} { set dir . } set file [file join $dir $name] if {[file executable $file] && ![file isdirectory $file]} { set auto_execs($name) 1 return 1 } } return 0 } } # auto_reset -- # Destroy all cached information for auto-loading and auto-execution, # so that the information gets recomputed the next time it's needed. # Also delete any procedures that are listed in the auto-load index # except those related to auto-loading. # # Arguments: # None. proc auto_reset {} { global auto_execs auto_index auto_oldpath foreach p [info procs] { if {[info exists auto_index($p)] && ($p != "unknown") && ![string match auto_* $p]} { rename $p {} } } catch {unset auto_execs} catch {unset auto_index} catch {unset auto_oldpath} } # auto_mkindex -- # Regenerate a tclIndex file from Tcl source files. Takes as argument # the name of the directory in which the tclIndex file is to be placed, # followed by any number of glob patterns to use in that directory to # locate all of the relevant files. # # Arguments: # dir - Name of the directory in which to create an index. # args - Any number of additional arguments giving the # names of files within dir. If no additional # are given auto_mkindex will look for *.tcl. proc auto_mkindex {dir args} { global errorCode errorInfo set oldDir [pwd] cd $dir set dir [pwd] append index "# Tcl autoload index file, version 2.0\n" append index "# This file is generated by the \"auto_mkindex\" command\n" append index "# and sourced to set up indexing information for one or\n" append index "# more commands. Typically each line is a command that\n" append index "# sets an element in the auto_index array, where the\n" append index "# element name is the name of a command and the value is\n" append index "# a script that loads the command.\n\n" if {$args == ""} { set args *.tcl } foreach file [eval glob $args] { set f "" set error [catch { set f [open $file] while {[gets $f line] >= 0} { if [regexp {^proc[ ]+([^ ]*)} $line match procName] { append index "set [list auto_index($procName)]" append index " \[list source \[file join \$dir [list $file]\]\]\n" } } close $f } msg] if $error { set code $errorCode set info $errorInfo catch {close $f} cd $oldDir error $msg $info $code } } set f "" set error [catch { set f [open tclIndex w] puts $f $index nonewline close $f cd $oldDir } msg] if $error { set code $errorCode set info $errorInfo catch {close $f} cd $oldDir error $msg $info $code } } # pkg_mkIndex -- # This procedure creates a package index in a given directory. The # package index consists of a "pkgIndex.tcl" file whose contents are # a Tcl script that sets up package information with "package require" # commands. The commands describe all of the packages defined by the # files given as arguments. # # Arguments: # dir - Name of the directory in which to create the index. # args - Any number of additional arguments, each giving # a glob pattern that matches the names of one or # more shared libraries or Tcl script files in # dir. proc pkg_mkIndex {dir args} { global errorCode errorInfo append index "# Tcl package index file, version 1.0\n" append index "# This file is generated by the \"pkg_mkIndex\" command\n" append index "# and sourced either when an application starts up or\n" append index "# by a \"package unknown\" script. It invokes the\n" append index "# \"package ifneeded\" command to set up package-related\n" append index "# information so that packages will be loaded automatically\n" append index "# in response to \"package require\" commands. When this\n" append index "# script is sourced, the variable \$dir must contain the\n" append index "# full path name of this file's directory.\n" set oldDir [pwd] cd $dir foreach file [eval glob $args] { # For each file, figure out what commands and packages it provides. # To do this, create a child interpreter, load the file into the # interpreter, and get a list of the new commands and packages # that are defined. Define an empty "package unknown" script so # that there are no recursive package inclusions. set c [interp create] $c eval [list set file $file] if [catch { $c eval { proc dummy args {} package unknown dummy set origCmds [info commands] set dir "" ;# in case file is pkgIndex.tcl set pkgs "" # The "file join ." command below is necessary. Without it, # if the file name has no \'s and we're on UNIX, the # LD_LIBRARY_PATH search mechanism will be invoked, which # could cause the wrong file to be used. if [catch {load [file join . $file]}] { if [catch {source $file}] { puts $errorInfo error "can't either load or source $file" } else { set type source } } else { set type load } foreach i [info commands] { set cmds($i) 1 } foreach i $origCmds { catch {unset cmds($i)} } foreach i [package names] { if {([string compare [package provide $i] ""] != 0) && ([string compare $i Tcl] != 0)} { lappend pkgs [list $i [package provide $i]] } } } } msg] { interp delete $c error $msg $errorInfo $errorCode } foreach pkg [$c eval set pkgs] { lappend files($pkg) [list $file [$c eval set type] \ [lsort [$c eval array names cmds]]] } interp delete $c } foreach pkg [lsort [array names files]] { append index "\npackage ifneeded $pkg\ \"tclPkgSetup \$dir [lrange $pkg 0 0] [lrange $pkg 1 1]\ [list $files($pkg)]\"" } set f [open pkgIndex.tcl w] puts $f $index close $f cd $oldDir } # tclPkgSetup -- # This is a utility procedure use by pkgIndex.tcl files. It is invoked # as part of a "package ifneeded" script. It calls "package provide" # to indicate that a package is available, then sets entries in the # auto_index array so that the package's files will be auto-loaded when # the commands are used. # # Arguments: # dir - Directory containing all the files for this package. # pkg - Name of the package (no version number). # version - Version number for the package, such as 2.1.3. # files - List of files that constitute the package. Each # element is a sub-list with three elements. The first # is the name of a file relative to $dir, the second is # "load" or "source", indicating whether the file is a # loadable binary or a script to source, and the third # is a list of commands defined by this file. proc tclPkgSetup {dir pkg version files} { global auto_index package provide $pkg $version foreach fileInfo $files { set f [lindex $fileInfo 0] set type [lindex $fileInfo 1] foreach cmd [lindex $fileInfo 2] { if {$type == "load"} { set auto_index($cmd) [list load [file join $dir $f] $pkg] } else { set auto_index($cmd) [list source [file join $dir $f]] } } } } # tclPkgUnknown -- # This procedure provides the default for the "package unknown" function. # It is invoked when a package that's needed can't be found. It scans # the auto_path directories looking for pkgIndex.tcl files and sources any # such files that are found to setup the package database. # # Arguments: # name - Name of desired package. Not used. # version - Version of desired package. Not used. # exact - Either "-exact" or omitted. Not used. proc tclPkgUnknown {name version {exact {}}} { global auto_path if ![info exists auto_path] { return } for {set i [expr [llength $auto_path] - 1]} {$i >= 0} {incr i -1} { set dir [lindex $auto_path $i] set file [file join $dir pkgIndex.tcl] if [file readable $file] { source $file } } } # tk.tcl -- # # Initialization script normally executed in the interpreter for each # Tk-based application. Arranges class bindings for widgets. # # SCCS: @(#) tk.tcl 1.81 96/02/16 10:48:13 # # Copyright (c) 1992-1994 The Regents of the University of California. # Copyright (c) 1994-1996 Sun Microsystems, Inc. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # Insist on running with compatible versions of Tcl and Tk. package require -exact Tk 4.1 package require -exact Tcl 7.5 # Add Tk's directory to the end of the auto-load search path, if it # isn't already on the path: if {[lsearch -exact $auto_path $tk_library] < 0} { lappend auto_path $tk_library } # Turn off strict Motif look and feel as a default. set tk_strictMotif 0 # tkScreenChanged -- # This procedure is invoked by the binding mechanism whenever the # "current" screen is changing. The procedure does two things. # First, it uses "upvar" to make global variable "tkPriv" point at an # array variable that holds state for the current display. Second, # it initializes the array if it didn't already exist. # # Arguments: # screen - The name of the new screen. proc tkScreenChanged screen { set disp [file rootname $screen] uplevel #0 upvar #0 tkPriv.$disp tkPriv global tkPriv if [info exists tkPriv] { set tkPriv(screen) $screen return } set tkPriv(afterId) {} set tkPriv(buttons) 0 set tkPriv(buttonWindow) {} set tkPriv(dragging) 0 set tkPriv(focus) {} set tkPriv(grab) {} set tkPriv(initPos) {} set tkPriv(inMenubutton) {} set tkPriv(listboxPrev) {} set tkPriv(mouseMoved) 0 set tkPriv(oldGrab) {} set tkPriv(popup) {} set tkPriv(postedMb) {} set tkPriv(pressX) 0 set tkPriv(pressY) 0 set tkPriv(screen) $screen set tkPriv(selectMode) char set tkPriv(window) {} } # Do initial setup for tkPriv, so that it is always bound to something # (otherwise, if someone references it, it may get set to a non-upvar-ed # value, which will cause trouble later). tkScreenChanged [winfo screen .] # ---------------------------------------------------------------------- # Read in files that define all of the class bindings. # ---------------------------------------------------------------------- if {$tcl_platform(platform) != "macintosh"} { } # ---------------------------------------------------------------------- # Default bindings for keyboard traversal. # ---------------------------------------------------------------------- bind all {focus [tk_focusNext %W]} bind all {focus [tk_focusPrev %W]} # tkCancelRepeat -- # This procedure is invoked to cancel an auto-repeat action described # by tkPriv(afterId). It's used by several widgets to auto-scroll # the widget when the mouse is dragged out of the widget with a # button pressed. # # Arguments: # None. proc tkCancelRepeat {} { global tkPriv after cancel $tkPriv(afterId) set tkPriv(afterId) {} } # bgerror.tcl -- # # This file contains a default version of the bgerror procedure. It # posts a dialog box with the error message and gives the user a chance # to see a more detailed stack trace. # # SCCS: @(#) bgerror.tcl 1.8 96/02/16 10:48:14 # # Copyright (c) 1992-1994 The Regents of the University of California. # Copyright (c) 1994-1995 Sun Microsystems, Inc. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # bgerror -- # This is the default version of bgerror. It posts a dialog box containing # the error message and gives the user a chance to ask to see a stack # trace. # Arguments: # err - The error message. proc bgerror err { global errorInfo set info $errorInfo set button [tk_dialog .bgerrorDialog "Error in Tcl Script" \ "Error: $err" error 0 OK "Skip Messages" "Stack Trace"] if {$button == 0} { return } elseif {$button == 1} { return -code break } set w .bgerrorTrace catch {destroy $w} toplevel $w -class ErrorTrace wm minsize $w 1 1 wm title $w "Stack Trace for Error" wm iconname $w "Stack Trace" button $w.ok -text OK -command "destroy $w" text $w.text -relief sunken -bd 2 -yscrollcommand "$w.scroll set" \ -setgrid true -width 60 -height 20 scrollbar $w.scroll -relief sunken -command "$w.text yview" pack $w.ok -side bottom -padx 3m -pady 2m pack $w.scroll -side right -fill y pack $w.text -side left -expand yes -fill both $w.text insert 0.0 $info $w.text mark set insert 0.0 # Center the window on the screen. wm withdraw $w update idletasks set x [expr [winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \ - [winfo vrootx [winfo parent $w]]] set y [expr [winfo screenheight $w]/2 - [winfo reqheight $w]/2 \ - [winfo vrooty [winfo parent $w]]] wm geom $w +$x+$y wm deiconify $w # Be sure to release any grabs that might be present on the # screen, since they could make it impossible for the user # to interact with the stack trace. if {[grab current .] != ""} { grab release [grab current .] } } # button.tcl -- # # This file defines the default bindings for Tk label, button, # checkbutton, and radiobutton widgets and provides procedures # that help in implementing those bindings. # # SCCS: @(#) button.tcl 1.19 96/02/20 13:01:32 # # Copyright (c) 1992-1994 The Regents of the University of California. # Copyright (c) 1994 Sun Microsystems, Inc. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # #------------------------------------------------------------------------- # The code below creates the default class bindings for buttons. #------------------------------------------------------------------------- bind Button {} bind Button { tkButtonEnter %W } bind Button { tkButtonLeave %W } bind Button <1> { tkButtonDown %W } bind Button { tkButtonUp %W } bind Button { tkButtonInvoke %W } bind Checkbutton {} bind Checkbutton { tkButtonEnter %W } bind Checkbutton { tkButtonLeave %W } bind Checkbutton <1> { tkCheckRadioInvoke %W } bind Checkbutton { tkCheckRadioInvoke %W } bind Checkbutton { if !$tk_strictMotif { tkCheckRadioInvoke %W } } bind Radiobutton {} bind Radiobutton { tkButtonEnter %W } bind Radiobutton { tkButtonLeave %W } bind Radiobutton <1> { tkCheckRadioInvoke %W } bind Radiobutton { tkCheckRadioInvoke %W } bind Radiobutton { if !$tk_strictMotif { tkCheckRadioInvoke %W } } # tkButtonEnter -- # The procedure below is invoked when the mouse pointer enters a # button widget. It records the button we're in and changes the # state of the button to active unless the button is disabled. # # Arguments: # w - The name of the widget. proc tkButtonEnter {w} { global tkPriv if {[$w cget -state] != "disabled"} { $w config -state active if {$tkPriv(buttonWindow) == $w} { $w configure -state active -relief sunken } } set tkPriv(window) $w } # tkButtonLeave -- # The procedure below is invoked when the mouse pointer leaves a # button widget. It changes the state of the button back to # inactive. If we're leaving the button window with a mouse button # pressed (tkPriv(buttonWindow) == $w), restore the relief of the # button too. # # Arguments: # w - The name of the widget. proc tkButtonLeave w { global tkPriv if {[$w cget -state] != "disabled"} { $w config -state normal } if {$w == $tkPriv(buttonWindow)} { $w configure -relief $tkPriv(relief) } set tkPriv(window) "" } # tkButtonDown -- # The procedure below is invoked when the mouse button is pressed in # a button widget. It records the fact that the mouse is in the button, # saves the button's relief so it can be restored later, and changes # the relief to sunken. # # Arguments: # w - The name of the widget. proc tkButtonDown w { global tkPriv set tkPriv(relief) [lindex [$w config -relief] 4] if {[$w cget -state] != "disabled"} { set tkPriv(buttonWindow) $w $w config -relief sunken } } # tkButtonUp -- # The procedure below is invoked when the mouse button is released # in a button widget. It restores the button's relief and invokes # the command as long as the mouse hasn't left the button. # # Arguments: # w - The name of the widget. proc tkButtonUp w { global tkPriv if {$w == $tkPriv(buttonWindow)} { set tkPriv(buttonWindow) "" $w config -relief $tkPriv(relief) if {($w == $tkPriv(window)) && ([$w cget -state] != "disabled")} { uplevel #0 [list $w invoke] } } } # tkButtonInvoke -- # The procedure below is called when a button is invoked through # the keyboard. It simulate a press of the button via the mouse. # # Arguments: # w - The name of the widget. proc tkButtonInvoke w { if {[$w cget -state] != "disabled"} { set oldRelief [$w cget -relief] set oldState [$w cget -state] $w configure -state active -relief sunken update idletasks after 100 $w configure -state $oldState -relief $oldRelief uplevel #0 [list $w invoke] } } # tkCheckRadioInvoke -- # The procedure below is invoked when the mouse button is pressed in # a checkbutton or radiobutton widget, or when the widget is invoked # through the keyboard. It invokes the widget if it # isn't disabled. # # Arguments: # w - The name of the widget. proc tkCheckRadioInvoke w { if {[$w cget -state] != "disabled"} { uplevel #0 [list $w invoke] } } # dialog.tcl -- # # This file defines the procedure tk_dialog, which creates a dialog # box containing a bitmap, a message, and one or more buttons. # # SCCS: @(#) dialog.tcl 1.25 96/04/10 15:43:33 # # Copyright (c) 1992-1993 The Regents of the University of California. # Copyright (c) 1994-1996 Sun Microsystems, Inc. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # # tk_dialog: # # This procedure displays a dialog box, waits for a button in the dialog # to be invoked, then returns the index of the selected button. # # Arguments: # w - Window to use for dialog top-level. # title - Title to display in dialog's decorative frame. # text - Message to display in dialog. # bitmap - Bitmap to display in dialog (empty string means none). # default - Index of button that is to display the default ring # (-1 means none). # args - One or more strings to display in buttons across the # bottom of the dialog box. proc tk_dialog {w title text bitmap default args} { global tkPriv # 1. Create the top-level window and divide it into top # and bottom parts. catch {destroy $w} toplevel $w -class Dialog wm title $w $title wm iconname $w Dialog wm protocol $w WM_DELETE_WINDOW { } # The following command has been removed because if it is present # the dialog won't be posted if [winfo parent $w] is iconified. # wm transient $w [winfo toplevel [winfo parent $w]] frame $w.bot -relief raised -bd 1 pack $w.bot -side bottom -fill both frame $w.top -relief raised -bd 1 pack $w.top -side top -fill both -expand 1 # 2. Fill the top part with bitmap and message (use the option # database for -wraplength so that it can be overridden by # the caller). option add *Dialog.msg.wrapLength 3i widgetDefault label $w.msg -justify left -text $text catch {$w.msg configure -font \ -Adobe-Times-Medium-R-Normal--*-180-*-*-*-*-*-* } pack $w.msg -in $w.top -side right -expand 1 -fill both -padx 3m -pady 3m if {$bitmap != ""} { label $w.bitmap -bitmap $bitmap pack $w.bitmap -in $w.top -side left -padx 3m -pady 3m } # 3. Create a row of buttons at the bottom of the dialog. set i 0 foreach but $args { button $w.button$i -text $but -command "set tkPriv(button) $i" if {$i == $default} { frame $w.default -relief sunken -bd 1 raise $w.button$i $w.default pack $w.default -in $w.bot -side left -expand 1 -padx 3m -pady 2m pack $w.button$i -in $w.default -padx 2m -pady 2m } else { pack $w.button$i -in $w.bot -side left -expand 1 \ -padx 3m -pady 2m } incr i } # 4. Create a binding for on the dialog if there is a # default button. if {$default >= 0} { bind $w " $w.button$default configure -state active -relief sunken update idletasks after 100 set tkPriv(button) $default " } # 5. Withdraw the window, then update all the geometry information # so we know how big it wants to be, then center the window in the # display and de-iconify it. wm withdraw $w update idletasks set x [expr [winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \ - [winfo vrootx [winfo parent $w]]] set y [expr [winfo screenheight $w]/2 - [winfo reqheight $w]/2 \ - [winfo vrooty [winfo parent $w]]] wm geom $w +$x+$y wm deiconify $w # 6. Set a grab and claim the focus too. set oldFocus [focus] set oldGrab [grab current $w] if {$oldGrab != ""} { set grabStatus [grab status $oldGrab] } grab $w if {$default >= 0} { focus $w.button$default } else { focus $w } # 7. Wait for the user to respond, then restore the focus and # return the index of the selected button. Restore the focus # before deleting the window, since otherwise the window manager # may take the focus away so we can't redirect it. Finally, # restore any grab that was in effect. tkwait variable tkPriv(button) catch {focus $oldFocus} destroy $w if {$oldGrab != ""} { if {$grabStatus == "global"} { grab -global $oldGrab } else { grab $oldGrab } } return $tkPriv(button) } # entry.tcl -- # # This file defines the default bindings for Tk entry widgets and provides # procedures that help in implementing those bindings. # # SCCS: @(#) entry.tcl 1.41 96/04/16 11:42:21 # # Copyright (c) 1992-1994 The Regents of the University of California. # Copyright (c) 1994-1996 Sun Microsystems, Inc. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # #------------------------------------------------------------------------- # Elements of tkPriv that are used in this file: # # afterId - If non-null, it means that auto-scanning is underway # and it gives the "after" id for the next auto-scan # command to be executed. # mouseMoved - Non-zero means the mouse has moved a significant # amount since the button went down (so, for example, # start dragging out a selection). # pressX - X-coordinate at which the mouse button was pressed. # selectMode - The style of selection currently underway: # char, word, or line. # x, y - Last known mouse coordinates for scanning # and auto-scanning. #------------------------------------------------------------------------- # tkEntryClipboardKeysyms -- # This procedure is invoked to identify the keys that correspond to # the "copy", "cut", and "paste" functions for the clipboard. # # Arguments: # copy - Name of the key (keysym name plus modifiers, if any, # such as "Meta-y") used for the copy operation. # cut - Name of the key used for the cut operation. # paste - Name of the key used for the paste operation. proc tkEntryClipboardKeysyms {copy cut paste} { bind Entry <$copy> { if {[selection own -displayof %W] == "%W"} { clipboard clear -displayof %W catch { clipboard append -displayof %W [selection get -displayof %W] } } } bind Entry <$cut> { if {[selection own -displayof %W] == "%W"} { clipboard clear -displayof %W catch { clipboard append -displayof %W [selection get -displayof %W] %W delete sel.first sel.last } } } bind Entry <$paste> { catch { %W insert insert [selection get -displayof %W \ -selection CLIPBOARD] } } } #------------------------------------------------------------------------- # The code below creates the default class bindings for entries. #------------------------------------------------------------------------- # Standard Motif bindings: bind Entry <1> { tkEntryButton1 %W %x %W selection clear } bind Entry { set tkPriv(x) %x tkEntryMouseSelect %W %x } bind Entry { set tkPriv(selectMode) word tkEntryMouseSelect %W %x catch {%W icursor sel.first} } bind Entry { set tkPriv(selectMode) line tkEntryMouseSelect %W %x %W icursor 0 } bind Entry { set tkPriv(selectMode) char %W selection adjust @%x } bind Entry { set tkPriv(selectMode) word tkEntryMouseSelect %W %x } bind Entry { set tkPriv(selectMode) line tkEntryMouseSelect %W %x } bind Entry { set tkPriv(x) %x tkEntryAutoScan %W } bind Entry { tkCancelRepeat } bind Entry { tkCancelRepeat } bind Entry { %W icursor @%x } bind Entry { if {!$tkPriv(mouseMoved) || $tk_strictMotif} { tkEntryPaste %W %x } } bind Entry { tkEntrySetCursor %W [expr [%W index insert] - 1] } bind Entry { tkEntrySetCursor %W [expr [%W index insert] + 1] } bind Entry { tkEntryKeySelect %W [expr [%W index insert] - 1] tkEntrySeeInsert %W } bind Entry { tkEntryKeySelect %W [expr [%W index insert] + 1] tkEntrySeeInsert %W } bind Entry { tkEntrySetCursor %W \ [string wordstart [%W get] [expr [%W index insert] - 1]] } bind Entry { tkEntrySetCursor %W [string wordend [%W get] [%W index insert]] } bind Entry { tkEntryKeySelect %W \ [string wordstart [%W get] [expr [%W index insert] - 1]] tkEntrySeeInsert %W } bind Entry { tkEntryKeySelect %W [string wordend [%W get] [%W index insert]] tkEntrySeeInsert %W } bind Entry { tkEntrySetCursor %W 0 } bind Entry { tkEntryKeySelect %W 0 tkEntrySeeInsert %W } bind Entry { tkEntrySetCursor %W end } bind Entry { tkEntryKeySelect %W end tkEntrySeeInsert %W } bind Entry { if [%W selection present] { %W delete sel.first sel.last } else { %W delete insert } } bind Entry { tkEntryBackspace %W } bind Entry { %W selection from insert } bind Entry { tkListboxBeginSelect %W [%W index active] } bind Listbox { tkListboxBeginExtend %W [%W index active] } bind Listbox { tkListboxBeginExtend %W [%W index active] } bind Listbox { tkListboxCancel %W } bind Listbox { tkListboxSelectAll %W } bind Listbox { if {[%W cget -selectmode] != "browse"} { %W selection clear 0 end } } # Additional Tk bindings that aren't part of the Motif look and feel: bind Listbox <2> { %W scan mark %x %y } bind Listbox { %W scan dragto %x %y } # tkListboxBeginSelect -- # # This procedure is typically invoked on button-1 presses. It begins # the process of making a selection in the listbox. Its exact behavior # depends on the selection mode currently in effect for the listbox; # see the Motif documentation for details. # # Arguments: # w - The listbox widget. # el - The element for the selection operation (typically the # one under the pointer). Must be in numerical form. proc tkListboxBeginSelect {w el} { global tkPriv if {[$w cget -selectmode] == "multiple"} { if [$w selection includes $el] { $w selection clear $el } else { $w selection set $el } } else { $w selection clear 0 end $w selection set $el $w selection anchor $el set tkPriv(listboxSelection) {} set tkPriv(listboxPrev) $el } } # tkListboxMotion -- # # This procedure is called to process mouse motion events while # button 1 is down. It may move or extend the selection, depending # on the listbox's selection mode. # # Arguments: # w - The listbox widget. # el - The element under the pointer (must be a number). proc tkListboxMotion {w el} { global tkPriv if {$el == $tkPriv(listboxPrev)} { return } set anchor [$w index anchor] switch [$w cget -selectmode] { browse { $w selection clear 0 end $w selection set $el set tkPriv(listboxPrev) $el } extended { set i $tkPriv(listboxPrev) if [$w selection includes anchor] { $w selection clear $i $el $w selection set anchor $el } else { $w selection clear $i $el $w selection clear anchor $el } while {($i < $el) && ($i < $anchor)} { if {[lsearch $tkPriv(listboxSelection) $i] >= 0} { $w selection set $i } incr i } while {($i > $el) && ($i > $anchor)} { if {[lsearch $tkPriv(listboxSelection) $i] >= 0} { $w selection set $i } incr i -1 } set tkPriv(listboxPrev) $el } } } # tkListboxBeginExtend -- # # This procedure is typically invoked on shift-button-1 presses. It # begins the process of extending a selection in the listbox. Its # exact behavior depends on the selection mode currently in effect # for the listbox; see the Motif documentation for details. # # Arguments: # w - The listbox widget. # el - The element for the selection operation (typically the # one under the pointer). Must be in numerical form. proc tkListboxBeginExtend {w el} { if {([$w cget -selectmode] == "extended") && [$w selection includes anchor]} { tkListboxMotion $w $el } } # tkListboxBeginToggle -- # # This procedure is typically invoked on control-button-1 presses. It # begins the process of toggling a selection in the listbox. Its # exact behavior depends on the selection mode currently in effect # for the listbox; see the Motif documentation for details. # # Arguments: # w - The listbox widget. # el - The element for the selection operation (typically the # one under the pointer). Must be in numerical form. proc tkListboxBeginToggle {w el} { global tkPriv if {[$w cget -selectmode] == "extended"} { set tkPriv(listboxSelection) [$w curselection] set tkPriv(listboxPrev) $el $w selection anchor $el if [$w selection includes $el] { $w selection clear $el } else { $w selection set $el } } } # tkListboxAutoScan -- # This procedure is invoked when the mouse leaves an entry window # with button 1 down. It scrolls the window up, down, left, or # right, depending on where the mouse left the window, and reschedules # itself as an "after" command so that the window continues to scroll until # the mouse moves back into the window or the mouse button is released. # # Arguments: # w - The entry window. proc tkListboxAutoScan {w} { global tkPriv if {![winfo exists $w]} return set x $tkPriv(x) set y $tkPriv(y) if {$y >= [winfo height $w]} { $w yview scroll 1 units } elseif {$y < 0} { $w yview scroll -1 units } elseif {$x >= [winfo width $w]} { $w xview scroll 2 units } elseif {$x < 0} { $w xview scroll -2 units } else { return } tkListboxMotion $w [$w index @$x,$y] set tkPriv(afterId) [after 50 tkListboxAutoScan $w] } # tkListboxUpDown -- # # Moves the location cursor (active element) up or down by one element, # and changes the selection if we're in browse or extended selection # mode. # # Arguments: # w - The listbox widget. # amount - +1 to move down one item, -1 to move back one item. proc tkListboxUpDown {w amount} { global tkPriv $w activate [expr [$w index active] + $amount] $w see active switch [$w cget -selectmode] { browse { $w selection clear 0 end $w selection set active } extended { $w selection clear 0 end $w selection set active $w selection anchor active set tkPriv(listboxPrev) [$w index active] set tkPriv(listboxSelection) {} } } } # tkListboxExtendUpDown -- # # Does nothing unless we're in extended selection mode; in this # case it moves the location cursor (active element) up or down by # one element, and extends the selection to that point. # # Arguments: # w - The listbox widget. # amount - +1 to move down one item, -1 to move back one item. proc tkListboxExtendUpDown {w amount} { if {[$w cget -selectmode] != "extended"} { return } $w activate [expr [$w index active] + $amount] $w see active tkListboxMotion $w [$w index active] } # tkListboxDataExtend # # This procedure is called for key-presses such as Shift-KEndData. # If the selection mode isn't multiple or extend then it does nothing. # Otherwise it moves the active element to el and, if we're in # extended mode, extends the selection to that point. # # Arguments: # w - The listbox widget. # el - An integer element number. proc tkListboxDataExtend {w el} { set mode [$w cget -selectmode] if {$mode == "extended"} { $w activate $el $w see $el if [$w selection includes anchor] { tkListboxMotion $w $el } } elseif {$mode == "multiple"} { $w activate $el $w see $el } } # tkListboxCancel # # This procedure is invoked to cancel an extended selection in # progress. If there is an extended selection in progress, it # restores all of the items between the active one and the anchor # to their previous selection state. # # Arguments: # w - The listbox widget. proc tkListboxCancel w { global tkPriv if {[$w cget -selectmode] != "extended"} { return } set first [$w index anchor] set last $tkPriv(listboxPrev) if {$first > $last} { set tmp $first set first $last set last $tmp } $w selection clear $first $last while {$first <= $last} { if {[lsearch $tkPriv(listboxSelection) $first] >= 0} { $w selection set $first } incr first } } # tkListboxSelectAll # # This procedure is invoked to handle the "select all" operation. # For single and browse mode, it just selects the active element. # Otherwise it selects everything in the widget. # # Arguments: # w - The listbox widget. proc tkListboxSelectAll w { set mode [$w cget -selectmode] if {($mode == "single") || ($mode == "browse")} { $w selection clear 0 end $w selection set active } else { $w selection set 0 end } } # menu.tcl -- # # This file defines the default bindings for Tk menus and menubuttons. # It also implements keyboard traversal of menus and implements a few # other utility procedures related to menus. # # SCCS: @(#) menu.tcl 1.65 96/04/16 09:02:01 # # Copyright (c) 1992-1994 The Regents of the University of California. # Copyright (c) 1994-1996 Sun Microsystems, Inc. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # #------------------------------------------------------------------------- # Elements of tkPriv that are used in this file: # # cursor - Saves the -cursor option for the posted menubutton. # focus - Saves the focus during a menu selection operation. # Focus gets restored here when the menu is unposted. # grabGlobal - Used in conjunction with tkPriv(oldGrab): if # tkPriv(oldGrab) is non-empty, then tkPriv(grabGlobal) # contains either an empty string or "-global" to # indicate whether the old grab was a local one or # a global one. # inMenubutton - The name of the menubutton widget containing # the mouse, or an empty string if the mouse is # not over any menubutton. # oldGrab - Window that had the grab before a menu was posted. # Used to restore the grab state after the menu # is unposted. Empty string means there was no # grab previously set. # popup - If a menu has been popped up via tk_popup, this # gives the name of the menu. Otherwise this # value is empty. # postedMb - Name of the menubutton whose menu is currently # posted, or an empty string if nothing is posted # A grab is set on this widget. # relief - Used to save the original relief of the current # menubutton. # window - When the mouse is over a menu, this holds the # name of the menu; it's cleared when the mouse # leaves the menu. #------------------------------------------------------------------------- #------------------------------------------------------------------------- # Overall note: # This file is tricky because there are four different ways that menus # can be used: # # 1. As a pulldown from a menubutton. This is the most common usage. # In this style, the variable tkPriv(postedMb) identifies the posted # menubutton. # 2. As a torn-off menu copied from some other menu. In this style # tkPriv(postedMb) is empty, and the top-level menu is no # override-redirect. # 3. As an option menu, triggered from an option menubutton. In thi # style tkPriv(postedMb) identifies the posted menubutton. # 4. As a popup menu. In this style tkPriv(postedMb) is empty and # the top-level menu is override-redirect. # # The various binding procedures use the state described above to # distinguish the various cases and take different actions in each # case. #------------------------------------------------------------------------- #------------------------------------------------------------------------- # The code below creates the default class bindings for menus # and menubuttons. #------------------------------------------------------------------------- bind Menubutton {} bind Menubutton { tkMbEnter %W } bind Menubutton { tkMbLeave %W } bind Menubutton <1> { if {$tkPriv(inMenubutton) != ""} { tkMbPost $tkPriv(inMenubutton) %X %Y } } bind Menubutton { tkMbMotion %W up %X %Y } bind Menubutton { tkMbMotion %W down %X %Y } bind Menubutton { tkMbButtonUp %W } bind Menubutton { tkMbPost %W tkMenuFirstEntry [%W cget -menu] } # Must set focus when mouse enters a menu, in order to allow # mixed-mode processing using both the mouse and the keyboard. # Don't set the focus if the event comes from a grab release, # though: such an event can happen after as part of unposting # a cascaded chain of menus, after the focus has already been # restored to wherever it was before menu selection started. bind Menu {} bind Menu { set tkPriv(window) %W if {"%m" != "NotifyUngrab"} { focus %W } } bind Menu { tkMenuLeave %W %X %Y %s } bind Menu { tkMenuMotion %W %y %s } bind Menu { tkMenuButtonDown %W } bind Menu { tkMenuInvoke %W 1 } bind Menu { tkMenuInvoke %W 0 } bind Menu { tkMenuInvoke %W 0 } bind Menu { tkMenuEscape %W } bind Menu { tkMenuLeftRight %W left } bind Menu { tkMenuLeftRight %W right } bind Menu { tkMenuNextEntry %W -1 } bind Menu { tkMenuNextEntry %W +1 } bind Menu { tkTraverseWithinMenu %W %A } # The following bindings apply to all windows, and are used to # implement keyboard menu traversal. bind all { tkTraverseToMenu %W %A } bind all { tkFirstMenu %W } # tkMbEnter -- # This procedure is invoked when the mouse enters a menubutton # widget. It activates the widget unless it is disabled. Note: # this procedure is only invoked when mouse button 1 is *not* down. # The procedure tkMbB1Enter is invoked if the button is down. # # Arguments: # w - The name of the widget. proc tkMbEnter w { global tkPriv if {$tkPriv(inMenubutton) != ""} { tkMbLeave $tkPriv(inMenubutton) } set tkPriv(inMenubutton) $w if {[$w cget -state] != "disabled"} { $w configure -state active } } # tkMbLeave -- # This procedure is invoked when the mouse leaves a menubutton widget. # It de-activates the widget, if the widget still exists. # # Arguments: # w - The name of the widget. proc tkMbLeave w { global tkPriv set tkPriv(inMenubutton) {} if ![winfo exists $w] { return } if {[$w cget -state] == "active"} { $w configure -state normal } } # tkMbPost -- # Given a menubutton, this procedure does all the work of posting # its associated menu and unposting any other menu that is currently # posted. # # Arguments: # w - The name of the menubutton widget whose menu # is to be posted. # x, y - Root coordinates of cursor, used for positioning # option menus. If not specified, then the center # of the menubutton is used for an option menu. proc tkMbPost {w {x {}} {y {}}} { global tkPriv if {([$w cget -state] == "disabled") || ($w == $tkPriv(postedMb))} { return } set menu [$w cget -menu] if {$menu == ""} { return } if ![string match $w.* $menu] { error "can't post $menu: it isn't a descendant of $w (this is a new requirement in Tk versions 3.0 and later)" } set cur $tkPriv(postedMb) if {$cur != ""} { tkMenuUnpost {} } set tkPriv(cursor) [$w cget -cursor] set tkPriv(relief) [$w cget -relief] $w configure -cursor arrow $w configure -relief raised set tkPriv(postedMb) $w set tkPriv(focus) [focus] $menu activate none # If this looks like an option menubutton then post the menu so # that the current entry is on top of the mouse. Otherwise post # the menu just below the menubutton, as for a pull-down. if [$w cget -indicatoron] { if {$y == ""} { set x [expr [winfo rootx $w] + [winfo width $w]/2] set y [expr [winfo rooty $w] + [winfo height $w]/2] } tkPostOverPoint $menu $x $y [tkMenuFindName $menu [$w cget -text]] } else { $menu post [winfo rootx $w] [expr [winfo rooty $w]+[winfo height $w]] } focus $menu tkSaveGrabInfo $w grab -global $w } # tkMenuUnpost -- # This procedure unposts a given menu, plus all of its ancestors up # to (and including) a menubutton, if any. It also restores various # values to what they were before the menu was posted, and releases # a grab if there's a menubutton involved. Special notes: # 1. It's important to unpost all menus before releasing the grab, so # that any Enter-Leave events (e.g. from menu back to main # application) have mode NotifyGrab. # 2. Be sure to enclose various groups of commands in "catch" so that # the procedure will complete even if the menubutton or the menu # or the grab window has been deleted. # # Arguments: # menu - Name of a menu to unpost. Ignored if there # is a posted menubutton. proc tkMenuUnpost menu { global tkPriv set mb $tkPriv(postedMb) # Restore focus right away (otherwise X will take focus away when # the menu is unmapped and under some window managers (e.g. olvwm) # we'll lose the focus completely). catch {focus $tkPriv(focus)} set tkPriv(focus) "" # Unpost menu(s) and restore some stuff that's dependent on # what was posted. catch { if {$mb != ""} { set menu [$mb cget -menu] $menu unpost set tkPriv(postedMb) {} $mb configure -cursor $tkPriv(cursor) $mb configure -relief $tkPriv(relief) } elseif {$tkPriv(popup) != ""} { $tkPriv(popup) unpost set tkPriv(popup) {} } elseif {[wm overrideredirect $menu]} { # We're in a cascaded sub-menu from a torn-off menu or popup. # Unpost all the menus up to the toplevel one (but not # including the top-level torn-off one) and deactivate the # top-level torn off menu if there is one. while 1 { set parent [winfo parent $menu] if {([winfo class $parent] != "Menu") || ![winfo ismapped $parent]} { break } $parent activate none $parent postcascade none if {![wm overrideredirect $parent]} { break } set menu $parent } $menu unpost } } # Release grab, if any, and restore the previous grab, if there # was one. if {$menu != ""} { set grab [grab current $menu] if {$grab != ""} { grab release $grab } } if {$tkPriv(oldGrab) != ""} { # Be careful restoring the old grab, since it's window may not # be visible anymore. catch { if {$tkPriv(grabStatus) == "global"} { grab set -global $tkPriv(oldGrab) } else { grab set $tkPriv(oldGrab) } } set tkPriv(oldGrab) "" } } # tkMbMotion -- # This procedure handles mouse motion events inside menubuttons, and # also outside menubuttons when a menubutton has a grab (e.g. when a # menu selection operation is in progress). # # Arguments: # w - The name of the menubutton widget. # upDown - "down" means button 1 is pressed, "up" means # it isn't. # rootx, rooty - Coordinates of mouse, in (virtual?) root window. proc tkMbMotion {w upDown rootx rooty} { global tkPriv if {$tkPriv(inMenubutton) == $w} { return } set new [winfo containing $rootx $rooty] if {($new != $tkPriv(inMenubutton)) && (($new == "") || ([winfo toplevel $new] == [winfo toplevel $w]))} { if {$tkPriv(inMenubutton) != ""} { tkMbLeave $tkPriv(inMenubutton) } if {($new != "") && ([winfo class $new] == "Menubutton") && ([$new cget -indicatoron] == 0) && ([$w cget -indicatoron] == 0)} { if {$upDown == "down"} { tkMbPost $new $rootx $rooty } else { tkMbEnter $new } } } } # tkMbButtonUp -- # This procedure is invoked to handle button 1 releases for menubuttons. # If the release happens inside the menubutton then leave its menu # posted with element 0 activated. Otherwise, unpost the menu. # # Arguments: # w - The name of the menubutton widget. proc tkMbButtonUp w { global tkPriv if {($tkPriv(postedMb) == $w) && ($tkPriv(inMenubutton) == $w)} { tkMenuFirstEntry [$tkPriv(postedMb) cget -menu] } else { tkMenuUnpost {} } } # tkMenuMotion -- # This procedure is called to handle mouse motion events for menus. # It does two things. First, it resets the active element in the # menu, if the mouse is over the menu. Second, if a mouse button # is down, it posts and unposts cascade entries to match the mouse # position. # # Arguments: # menu - The menu window. # y - The y position of the mouse. # state - Modifier state (tells whether buttons are down). proc tkMenuMotion {menu y state} { global tkPriv if {$menu == $tkPriv(window)} { $menu activate @$y } if {($state & 0x1f00) != 0} { $menu postcascade active } } # tkMenuButtonDown -- # Handles button presses in menus. There are a couple of tricky things # here: # 1. Change the posted cascade entry (if any) to match the mouse position. # 2. If there is a posted menubutton, must grab to the menubutton; this # overrrides the implicit grab on button press, so that the menu # button can track mouse motions over other menubuttons and change # the posted menu. # 3. If there's no posted menubutton (e.g. because we're a torn-off menu # or one of its descendants) must grab to the top-level menu so that # we can track mouse motions across the entire menu hierarchy. # # Arguments: # menu - The menu window. proc tkMenuButtonDown menu { global tkPriv $menu postcascade active if {$tkPriv(postedMb) != ""} { grab -global $tkPriv(postedMb) } else { while {[wm overrideredirect $menu] && ([winfo class [winfo parent $menu]] == "Menu") && [winfo ismapped [winfo parent $menu]]} { set menu [winfo parent $menu] } # Don't update grab information if the grab window isn't changing. # Otherwise, we'll get an error when we unpost the menus and # restore the grab, since the old grab window will not be viewable # anymore. if {$menu != [grab current $menu]} { tkSaveGrabInfo $menu } # Must re-grab even if the grab window hasn't changed, in order # to release the implicit grab from the button press. grab -global $menu } } # tkMenuLeave -- # This procedure is invoked to handle Leave events for a menu. It # deactivates everything unless the active element is a cascade element # and the mouse is now over the submenu. # # Arguments: # menu - The menu window. # rootx, rooty - Root coordinates of mouse. # state - Modifier state. proc tkMenuLeave {menu rootx rooty state} { global tkPriv set tkPriv(window) {} if {[$menu index active] == "none"} { return } if {([$menu type active] == "cascade") && ([winfo containing $rootx $rooty] == [$menu entrycget active -menu])} { return } $menu activate none } # tkMenuInvoke -- # This procedure is invoked when button 1 is released over a menu. # It invokes the appropriate menu action and unposts the menu if # it came from a menubutton. # # Arguments: # w - Name of the menu widget. # buttonRelease - 1 means this procedure is called because of # a button release; 0 means because of keystroke. proc tkMenuInvoke {w buttonRelease} { global tkPriv if {$buttonRelease && ($tkPriv(window) == "")} { # Mouse was pressed over a menu without a menu button, then # dragged off the menu (possibly with a cascade posted) and # released. Unpost everything and quit. $w postcascade none $w activate none tkMenuUnpost $w return } if {[$w type active] == "cascade"} { $w postcascade active set menu [$w entrycget active -menu] tkMenuFirstEntry $menu } elseif {[$w type active] == "tearoff"} { tkMenuUnpost $w tkTearOffMenu $w } else { tkMenuUnpost $w uplevel #0 [list $w invoke active] } } # tkMenuEscape -- # This procedure is invoked for the Cancel (or Escape) key. It unposts # the given menu and, if it is the top-level menu for a menu button, # unposts the menu button as well. # # Arguments: # menu - Name of the menu window. proc tkMenuEscape menu { if {[winfo class [winfo parent $menu]] != "Menu"} { tkMenuUnpost $menu } else { tkMenuLeftRight $menu -1 } } # tkMenuLeftRight -- # This procedure is invoked to handle "left" and "right" traversal # motions in menus. It traverses to the next menu in a menu bar, # or into or out of a cascaded menu. # # Arguments: # menu - The menu that received the keyboard # event. # direction - Direction in which to move: "left" or "right" proc tkMenuLeftRight {menu direction} { global tkPriv # First handle traversals into and out of cascaded menus. if {$direction == "right"} { set count 1 if {[$menu type active] == "cascade"} { $menu postcascade active set m2 [$menu entrycget active -menu] if {$m2 != ""} { tkMenuFirstEntry $m2 } return } } else { set count -1 set m2 [winfo parent $menu] if {[winfo class $m2] == "Menu"} { $menu activate none focus $m2 # This code unposts any posted submenu in the parent. set tmp [$m2 index active] $m2 activate none $m2 activate $tmp return } } # Can't traverse into or out of a cascaded menu. Go to the next # or previous menubutton, if that makes sense. set w $tkPriv(postedMb) if {$w == ""} { return } set buttons [winfo children [winfo parent $w]] set length [llength $buttons] set i [expr [lsearch -exact $buttons $w] + $count] while 1 { while {$i < 0} { incr i $length } while {$i >= $length} { incr i -$length } set mb [lindex $buttons $i] if {([winfo class $mb] == "Menubutton") && ([$mb cget -state] != "disabled") && ([$mb cget -menu] != "") && ([[$mb cget -menu] index last] != "none")} { break } if {$mb == $w} { return } incr i $count } tkMbPost $mb tkMenuFirstEntry [$mb cget -menu] } # tkMenuNextEntry -- # Activate the next higher or lower entry in the posted menu, # wrapping around at the ends. Disabled entries are skipped. # # Arguments: # menu - Menu window that received the keystroke. # count - 1 means go to the next lower entry, # -1 means go to the next higher entry. proc tkMenuNextEntry {menu count} { global tkPriv if {[$menu index last] == "none"} { return } set length [expr [$menu index last]+1] set quitAfter $length set active [$menu index active] if {$active == "none"} { set i 0 } else { set i [expr $active + $count] } while 1 { if {$quitAfter <= 0} { # We've tried every entry in the menu. Either there are # none, or they're all disabled. Just give up. return } while {$i < 0} { incr i $length } while {$i >= $length} { incr i -$length } if {[catch {$menu entrycget $i -state} state] == 0} { if {$state != "disabled"} { break } } if {$i == $active} { return } incr i $count incr quitAfter -1 } $menu activate $i $menu postcascade $i } # tkMenuFind -- # This procedure searches the entire window hierarchy under w for # a menubutton that isn't disabled and whose underlined character # is "char". It returns the name of that window, if found, or an # empty string if no matching window was found. If "char" is an # empty string then the procedure returns the name of the first # menubutton found that isn't disabled. # # Arguments: # w - Name of window where key was typed. # char - Underlined character to search for; # may be either upper or lower case, and # will match either upper or lower case. proc tkMenuFind {w char} { global tkPriv set char [string tolower $char] foreach child [winfo child $w] { switch [winfo class $child] { Menubutton { set char2 [string index [$child cget -text] \ [$child cget -underline]] if {([string compare $char [string tolower $char2]] == 0) || ($char == "")} { if {[$child cget -state] != "disabled"} { return $child } } } Frame { set match [tkMenuFind $child $char] if {$match != ""} { return $match } } } } return {} } # tkTraverseToMenu -- # This procedure implements keyboard traversal of menus. Given an # ASCII character "char", it looks for a menubutton with that character # underlined. If one is found, it posts the menubutton's menu # # Arguments: # w - Window in which the key was typed (selects # a toplevel window). # char - Character that selects a menu. The case # is ignored. If an empty string, nothing # happens. proc tkTraverseToMenu {w char} { global tkPriv if {$char == ""} { return } while {[winfo class $w] == "Menu"} { if {$tkPriv(postedMb) == ""} { return } set w [winfo parent $w] } set w [tkMenuFind [winfo toplevel $w] $char] if {$w != ""} { tkMbPost $w tkMenuFirstEntry [$w cget -menu] } } # tkFirstMenu -- # This procedure traverses to the first menubutton in the toplevel # for a given window, and posts that menubutton's menu. # # Arguments: # w - Name of a window. Selects which toplevel # to search for menubuttons. proc tkFirstMenu w { set w [tkMenuFind [winfo toplevel $w] ""] if {$w != ""} { tkMbPost $w tkMenuFirstEntry [$w cget -menu] } } # tkTraverseWithinMenu # This procedure implements keyboard traversal within a menu. It # searches for an entry in the menu that has "char" underlined. If # such an entry is found, it is invoked and the menu is unposted. # # Arguments: # w - The name of the menu widget. # char - The character to look for; case is # ignored. If the string is empty then # nothing happens. proc tkTraverseWithinMenu {w char} { if {$char == ""} { return } set char [string tolower $char] set last [$w index last] if {$last == "none"} { return } for {set i 0} {$i <= $last} {incr i} { if [catch {set char2 [string index \ [$w entrycget $i -label] \ [$w entrycget $i -underline]]}] { continue } if {[string compare $char [string tolower $char2]] == 0} { if {[$w type $i] == "cascade"} { $w postcascade $i $w activate $i set m2 [$w entrycget $i -menu] if {$m2 != ""} { tkMenuFirstEntry $m2 } } else { tkMenuUnpost $w uplevel #0 [list $w invoke $i] } return } } } # tkMenuFirstEntry -- # Given a menu, this procedure finds the first entry that isn't # disabled or a tear-off or separator, and activates that entry. # However, if there is already an active entry in the menu (e.g., # because of a previous call to tkPostOverPoint) then the active # entry isn't changed. This procedure also sets the input focus # to the menu. # # Arguments: # menu - Name of the menu window (possibly empty). proc tkMenuFirstEntry menu { if {$menu == ""} { return } focus $menu if {[$menu index active] != "none"} { return } set last [$menu index last] if {$last == "none"} { return } for {set i 0} {$i <= $last} {incr i} { if {([catch {set state [$menu entrycget $i -state]}] == 0) && ($state != "disabled") && ([$menu type $i] != "tearoff")} { $menu activate $i return } } } # tkMenuFindName -- # Given a menu and a text string, return the index of the menu entry # that displays the string as its label. If there is no such entry, # return an empty string. This procedure is tricky because some names # like "active" have a special meaning in menu commands, so we can't # always use the "index" widget command. # # Arguments: # menu - Name of the menu widget. # s - String to look for. proc tkMenuFindName {menu s} { set i "" if {![regexp {^active$|^last$|^none$|^[0-9]|^@} $s]} { catch {set i [$menu index $s]} return $i } set last [$menu index last] if {$last == "none"} { return } for {set i 0} {$i <= $last} {incr i} { if ![catch {$menu entrycget $i -label} label] { if {$label == $s} { return $i } } } return "" } # tkPostOverPoint -- # This procedure posts a given menu such that a given entry in the # menu is centered over a given point in the root window. It also # activates the given entry. # # Arguments: # menu - Menu to post. # x, y - Root coordinates of point. # entry - Index of entry within menu to center over (x,y). # If omitted or specified as {}, then the menu's # upper-left corner goes at (x,y). proc tkPostOverPoint {menu x y {entry {}}} { if {$entry != {}} { if {$entry == [$menu index last]} { incr y [expr -([$menu yposition $entry] \ + [winfo reqheight $menu])/2] } else { incr y [expr -([$menu yposition $entry] \ + [$menu yposition [expr $entry+1]])/2] } incr x [expr -[winfo reqwidth $menu]/2] } $menu post $x $y if {($entry != {}) && ([$menu entrycget $entry -state] != "disabled")} { $menu activate $entry } } # tkSaveGrabInfo -- # Sets the variables tkPriv(oldGrab) and tkPriv(grabStatus) to record # the state of any existing grab on the w's display. # # Arguments: # w - Name of a window; used to select the display # whose grab information is to be recorded. proc tkSaveGrabInfo w { global tkPriv set tkPriv(oldGrab) [grab current $w] if {$tkPriv(oldGrab) != ""} { set tkPriv(grabStatus) [grab status $tkPriv(oldGrab)] } } # tk_popup -- # This procedure pops up a menu and sets things up for traversing # the menu and its submenus. # # Arguments: # menu - Name of the menu to be popped up. # x, y - Root coordinates at which to pop up the # menu. # entry - Index of a menu entry to center over (x,y). # If omitted or specified as {}, then menu's # upper-left corner goes at (x,y). proc tk_popup {menu x y {entry {}}} { global tkPriv if {($tkPriv(popup) != "") || ($tkPriv(postedMb) != "")} { tkMenuUnpost {} } tkPostOverPoint $menu $x $y $entry tkSaveGrabInfo $menu grab -global $menu set tkPriv(popup) $menu set tkPriv(focus) [focus] focus $menu } # palette.tcl -- # # This file contains procedures that change the color palette used # by Tk. # # SCCS: @(#) palette.tcl 1.2 96/02/16 10:48:25 # # Copyright (c) 1995 Sun Microsystems, Inc. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # tk_setPalette -- # Changes the default color scheme for a Tk application by setting # default colors in the option database and by modifying all of the # color options for existing widgets that have the default value. # # Arguments: # The arguments consist of either a single color name, which # will be used as the new background color (all other colors will # be computed from this) or an even number of values consisting of # option names and values. The name for an option is the one used # for the option database, such as activeForeground, not -activeforeground. proc tk_setPalette args { global tkPalette # Create an array that has the complete new palette. If some colors # aren't specified, compute them from other colors that are specified. if {[llength $args] == 1} { set new(background) [lindex $args 0] } else { array set new $args } if ![info exists new(background)] { error "must specify a background color" } if ![info exists new(foreground)] { set new(foreground) black } set bg [winfo rgb . $new(background)] set fg [winfo rgb . $new(foreground)] set darkerBg [format #%02x%02x%02x [expr (9*[lindex $bg 0])/2560] \ [expr (9*[lindex $bg 1])/2560] [expr (9*[lindex $bg 2])/2560]] foreach i {activeForeground insertBackground selectForeground \ highlightColor} { if ![info exists new($i)] { set new($i) $new(foreground) } } if ![info exists new(disabledForeground)] { set new(disabledForeground) [format #%02x%02x%02x \ [expr (3*[lindex $bg 0] + [lindex $fg 0])/1024] \ [expr (3*[lindex $bg 1] + [lindex $fg 1])/1024] \ [expr (3*[lindex $bg 2] + [lindex $fg 2])/1024]] } if ![info exists new(highlightBackground)] { set new(highlightBackground) $new(background) } if ![info exists new(activeBackground)] { # Pick a default active background that islighter than the # normal background. To do this, round each color component # up by 15% or 1/3 of the way to full white, whichever is # greater. foreach i {0 1 2} { set light($i) [expr [lindex $bg $i]/256] set inc1 [expr ($light($i)*15)/100] set inc2 [expr (255-$light($i))/3] if {$inc1 > $inc2} { incr light($i) $inc1 } else { incr light($i) $inc2 } if {$light($i) > 255} { set light($i) 255 } } set new(activeBackground) [format #%02x%02x%02x $light(0) \ $light(1) $light(2)] } if ![info exists new(selectBackground)] { set new(selectBackground) $darkerBg } if ![info exists new(troughColor)] { set new(troughColor) $darkerBg } if ![info exists new(selectColor)] { set new(selectColor) #b03060 } # Walk the widget hierarchy, recoloring all existing windows. # Before doing this, make sure that the tkPalette variable holds # the default values of all options, so that tkRecolorTree can # be sure to only change options that have their default values. # If the variable exists, then it is already correct (it was created # the last time this procedure was invoked). If the variable # doesn't exist, fill it in using the defaults from a few widgets. if ![info exists tkPalette] { checkbutton .c14732 entry .e14732 scrollbar .s14732 set tkPalette(activeBackground) \ [lindex [.c14732 configure -activebackground] 3] set tkPalette(activeForeground) \ [lindex [.c14732 configure -activeforeground] 3] set tkPalette(background) \ [lindex [.c14732 configure -background] 3] set tkPalette(disabledForeground) \ [lindex [.c14732 configure -disabledforeground] 3] set tkPalette(foreground) \ [lindex [.c14732 configure -foreground] 3] set tkPalette(highlightBackground) \ [lindex [.c14732 configure -highlightbackground] 3] set tkPalette(highlightColor) \ [lindex [.c14732 configure -highlightcolor] 3] set tkPalette(insertBackground) \ [lindex [.e14732 configure -insertbackground] 3] set tkPalette(selectColor) \ [lindex [.c14732 configure -selectcolor] 3] set tkPalette(selectBackground) \ [lindex [.e14732 configure -selectbackground] 3] set tkPalette(selectForeground) \ [lindex [.e14732 configure -selectforeground] 3] set tkPalette(troughColor) \ [lindex [.s14732 configure -troughcolor] 3] destroy .c14732 .e14732 .s14732 } tkRecolorTree . new # Change the option database so that future windows will get the # same colors. foreach option [array names new] { option add *$option $new($option) widgetDefault } # Save the options in the global variable tkPalette, for use the # next time we change the options. array set tkPalette [array get new] } # tkRecolorTree -- # This procedure changes the colors in a window and all of its # descendants, according to information provided by the colors # argument. It only modifies colors that have their default values # as specified by the tkPalette variable. # # Arguments: # w - The name of a window. This window and all its # descendants are recolored. # colors - The name of an array variable in the caller, # which contains color information. Each element # is named after a widget configuration option, and # each value is the value for that option. proc tkRecolorTree {w colors} { global tkPalette upvar $colors c foreach dbOption [array names c] { set option -[string tolower $dbOption] if ![catch {$w cget $option} value] { if {$value == $tkPalette($dbOption)} { $w configure $option $c($dbOption) } } } foreach child [winfo children $w] { tkRecolorTree $child c } } # tkDarken -- # Given a color name, computes a new color value that darkens (or # brightens) the given color by a given percent. # # Arguments: # color - Name of starting color. # perecent - Integer telling how much to brighten or darken as a # percent: 50 means darken by 50%, 110 means brighten # by 10%. proc tkDarken {color percent} { set l [winfo rgb . $color] set red [expr [lindex $l 0]/256] set green [expr [lindex $l 1]/256] set blue [expr [lindex $l 2]/256] set red [expr ($red*$percent)/100] if {$red > 255} { set red 255 } set green [expr ($green*$percent)/100] if {$green > 255} { set green 255 } set blue [expr ($blue*$percent)/100] if {$blue > 255} { set blue 255 } format #%02x%02x%02x $red $green $blue } # tk_bisque -- # Reset the Tk color palette to the old "bisque" colors. # # Arguments: # None. proc tk_bisque {} { tk_setPalette activeBackground #e6ceb1 activeForeground black \ background #ffe4c4 disabledForeground #b0b0b0 foreground black \ highlightBackground #ffe4c4 highlightColor black \ insertBackground black selectColor #b03060 \ selectBackground #e6ceb1 selectForeground black \ troughColor #cdb79e } # scale.tcl -- # # This file defines the default bindings for Tk scale widgets and provides # procedures that help in implementing the bindings. # # SCCS: @(#) scale.tcl 1.12 96/04/16 11:42:25 # # Copyright (c) 1994 The Regents of the University of California. # Copyright (c) 1994-1995 Sun Microsystems, Inc. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # #------------------------------------------------------------------------- # The code below creates the default class bindings for entries. #------------------------------------------------------------------------- # Standard Motif bindings: bind Scale { if $tk_strictMotif { set tkPriv(activeBg) [%W cget -activebackground] %W config -activebackground [%W cget -background] } tkScaleActivate %W %x %y } bind Scale { tkScaleActivate %W %x %y } bind Scale { if $tk_strictMotif { %W config -activebackground $tkPriv(activeBg) } if {[%W cget -state] == "active"} { %W configure -state normal } } bind Scale <1> { tkScaleButtonDown %W %x %y } bind Scale { tkScaleDrag %W %x %y } bind Scale { } bind Scale { } bind Scale { tkCancelRepeat tkScaleEndDrag %W tkScaleActivate %W %x %y } bind Scale <2> { tkScaleButton2Down %W %x %y } bind Scale { tkScaleDrag %W %x %y } bind Scale { } bind Scale { } bind Scale { tkCancelRepeat tkScaleEndDrag %W tkScaleActivate %W %x %y } bind Scale { tkScaleControlPress %W %x %y } bind Scale { tkScaleIncrement %W up little noRepeat } bind Scale { tkScaleIncrement %W down little noRepeat } bind Scale { tkScaleIncrement %W up little noRepeat } bind Scale { tkScaleIncrement %W down little noRepeat } bind Scale { tkScaleIncrement %W up big noRepeat } bind Scale { tkScaleIncrement %W down big noRepeat } bind Scale { tkScaleIncrement %W up big noRepeat } bind Scale { tkScaleIncrement %W down big noRepeat } bind Scale { %W set [%W cget -from] } bind Scale { %W set [%W cget -to] } # tkScaleActivate -- # This procedure is invoked to check a given x-y position in the # scale and activate the slider if the x-y position falls within # the slider. # # Arguments: # w - The scale widget. # x, y - Mouse coordinates. proc tkScaleActivate {w x y} { global tkPriv if {[$w cget -state] == "disabled"} { return; } if {[$w identify $x $y] == "slider"} { $w configure -state active } else { $w configure -state normal } } # tkScaleButtonDown -- # This procedure is invoked when a button is pressed in a scale. It # takes different actions depending on where the button was pressed. # # Arguments: # w - The scale widget. # x, y - Mouse coordinates of button press. proc tkScaleButtonDown {w x y} { global tkPriv set tkPriv(dragging) 0 set el [$w identify $x $y] if {$el == "trough1"} { tkScaleIncrement $w up little initial } elseif {$el == "trough2"} { tkScaleIncrement $w down little initial } elseif {$el == "slider"} { set tkPriv(dragging) 1 set tkPriv(initValue) [$w get] set coords [$w coords] set tkPriv(deltaX) [expr $x - [lindex $coords 0]] set tkPriv(deltaY) [expr $y - [lindex $coords 1]] $w configure -sliderrelief sunken } } # tkScaleDrag -- # This procedure is called when the mouse is dragged with # mouse button 1 down. If the drag started inside the slider # (i.e. the scale is active) then the scale's value is adjusted # to reflect the mouse's position. # # Arguments: # w - The scale widget. # x, y - Mouse coordinates. proc tkScaleDrag {w x y} { global tkPriv if !$tkPriv(dragging) { return } $w set [$w get [expr $x - $tkPriv(deltaX)] \ [expr $y - $tkPriv(deltaY)]] } # tkScaleEndDrag -- # This procedure is called to end an interactive drag of the # slider. It just marks the drag as over. # # Arguments: # w - The scale widget. proc tkScaleEndDrag {w} { global tkPriv set tkPriv(dragging) 0 $w configure -sliderrelief raised } # tkScaleIncrement -- # This procedure is invoked to increment the value of a scale and # to set up auto-repeating of the action if that is desired. The # way the value is incremented depends on the "dir" and "big" # arguments. # # Arguments: # w - The scale widget. # dir - "up" means move value towards -from, "down" means # move towards -to. # big - Size of increments: "big" or "little". # repeat - Whether and how to auto-repeat the action: "noRepeat" # means don't auto-repeat, "initial" means this is the # first action in an auto-repeat sequence, and "again" # means this is the second repetition or later. proc tkScaleIncrement {w dir big repeat} { global tkPriv if {![winfo exists $w]} return if {$big == "big"} { set inc [$w cget -bigincrement] if {$inc == 0} { set inc [expr abs([$w cget -to] - [$w cget -from])/10.0] } if {$inc < [$w cget -resolution]} { set inc [$w cget -resolution] } } else { set inc [$w cget -resolution] } if {([$w cget -from] > [$w cget -to]) ^ ($dir == "up")} { set inc [expr -$inc] } $w set [expr [$w get] + $inc] if {$repeat == "again"} { set tkPriv(afterId) [after [$w cget -repeatinterval] \ tkScaleIncrement $w $dir $big again] } elseif {$repeat == "initial"} { set delay [$w cget -repeatdelay] if {$delay > 0} { set tkPriv(afterId) [after $delay \ tkScaleIncrement $w $dir $big again] } } } # tkScaleControlPress -- # This procedure handles button presses that are made with the Control # key down. Depending on the mouse position, it adjusts the scale # value to one end of the range or the other. # # Arguments: # w - The scale widget. # x, y - Mouse coordinates where the button was pressed. proc tkScaleControlPress {w x y} { set el [$w identify $x $y] if {$el == "trough1"} { $w set [$w cget -from] } elseif {$el == "trough2"} { $w set [$w cget -to] } } # tkScaleButton2Down # This procedure is invoked when button 2 is pressed over a scale. # It sets the value to correspond to the mouse position and starts # a slider drag. # # Arguments: # w - The scrollbar widget. # x, y - Mouse coordinates within the widget. proc tkScaleButton2Down {w x y} { global tkPriv if {[$w cget -state] == "disabled"} { return; } $w configure -state active $w set [$w get $x $y] set tkPriv(dragging) 1 set tkPriv(initValue) [$w get] set coords "$x $y" set tkPriv(deltaX) 0 set tkPriv(deltaY) 0 } # tearoff.tcl -- # # This file contains procedures that implement tear-off menus. # # SCCS: @(#) tearoff.tcl 1.9 96/02/23 15:31:30 # # Copyright (c) 1994 The Regents of the University of California. # Copyright (c) 1994-1995 Sun Microsystems, Inc. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # tkTearoffMenu -- # Given the name of a menu, this procedure creates a torn-off menu # that is identical to the given menu (including nested submenus). # The new torn-off menu exists as a toplevel window managed by the # window manager. The return value is the name of the new menu. # # Arguments: # w - The menu to be torn-off (duplicated). proc tkTearOffMenu w { # Find a unique name to use for the torn-off menu. Find the first # ancestor of w that is a toplevel but not a menu, and use this as # the parent of the new menu. This guarantees that the torn off # menu will be on the same screen as the original menu. By making # it a child of the ancestor, rather than a child of the menu, it # can continue to live even if the menu is deleted; it will go # away when the toplevel goes away. set parent [winfo parent $w] while {([winfo toplevel $parent] != $parent) || ([winfo class $parent] == "Menu")} { set parent [winfo parent $parent] } if {$parent == "."} { set parent "" } for {set i 1} 1 {incr i} { set menu $parent.tearoff$i if ![winfo exists $menu] { break } } tkMenuDup $w $menu $menu configure -transient 0 # Pick a title for the new menu by looking at the parent of the # original: if the parent is a menu, then use the text of the active # entry. If it's a menubutton then use its text. set parent [winfo parent $w] switch [winfo class $parent] { Menubutton { wm title $menu [$parent cget -text] } Menu { wm title $menu [$parent entrycget active -label] } } $menu configure -tearoff 0 $menu post [winfo x $w] [winfo y $w] # Set tkPriv(focus) on entry: otherwise the focus will get lost # after keyboard invocation of a sub-menu (it will stay on the # submenu). bind $menu { set tkPriv(focus) %W } # If there is a -tearoffcommand option for the menu, invoke it # now. set cmd [$w cget -tearoffcommand] if {$cmd != ""} { uplevel #0 $cmd $w $menu } } # tkMenuDup -- # Given a menu (hierarchy), create a duplicate menu (hierarchy) # in a given window. # # Arguments: # src - Source window. Must be a menu. It and its # menu descendants will be duplicated at dst. # dst - Name to use for topmost menu in duplicate # hierarchy. proc tkMenuDup {src dst} { set cmd "menu $dst" foreach option [$src configure] { if {[llength $option] == 2} { continue } lappend cmd [lindex $option 0] [lindex $option 4] } eval $cmd set last [$src index last] if {$last == "none"} { return } for {set i [$src cget -tearoff]} {$i <= $last} {incr i} { set cmd "$dst add [$src type $i]" foreach option [$src entryconfigure $i] { lappend cmd [lindex $option 0] [lindex $option 4] } eval $cmd if {[$src type $i] == "cascade"} { tkMenuDup [$src entrycget $i -menu] $dst.m$i $dst entryconfigure $i -menu $dst.m$i } } # Duplicate the binding tags and bindings from the source menu. regsub -all . $src {\\&} quotedSrc regsub -all . $dst {\\&} quotedDst regsub -all $quotedSrc [bindtags $src] $dst x bindtags $dst $x foreach event [bind $src] { regsub -all $quotedSrc [bind $src $event] $dst x bind $dst $event $x } } # text.tcl -- # # This file defines the default bindings for Tk text widgets and provides # procedures that help in implementing the bindings. # # SCCS: @(#) text.tcl 1.44 96/04/16 11:42:24 # # Copyright (c) 1992-1994 The Regents of the University of California. # Copyright (c) 1994-1996 Sun Microsystems, Inc. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # #------------------------------------------------------------------------- # Elements of tkPriv that are used in this file: # # afterId - If non-null, it means that auto-scanning is underway # and it gives the "after" id for the next auto-scan # command to be executed. # char - Character position on the line; kept in order # to allow moving up or down past short lines while # still remembering the desired position. # mouseMoved - Non-zero means the mouse has moved a significant # amount since the button went down (so, for example, # start dragging out a selection). # prevPos - Used when moving up or down lines via the keyboard. # Keeps track of the previous insert position, so # we can distinguish a series of ups and downs, all # in a row, from a new up or down. # selectMode - The style of selection currently underway: # char, word, or line. # x, y - Last known mouse coordinates for scanning # and auto-scanning. #------------------------------------------------------------------------- # tkTextClipboardKeysyms -- # This procedure is invoked to identify the keys that correspond to # the "copy", "cut", and "paste" functions for the clipboard. # # Arguments: # copy - Name of the key (keysym name plus modifiers, if any, # such as "Meta-y") used for the copy operation. # cut - Name of the key used for the cut operation. # paste - Name of the key used for the paste operation. proc tkTextClipboardKeysyms {copy cut paste} { bind Text <$copy> {tk_textCopy %W} bind Text <$cut> {tk_textCut %W} bind Text <$paste> {tk_textPaste %W} } #------------------------------------------------------------------------- # The code below creates the default class bindings for entries. #------------------------------------------------------------------------- # Standard Motif bindings: bind Text <1> { tkTextButton1 %W %x %y %W tag remove sel 0.0 end } bind Text { set tkPriv(x) %x set tkPriv(y) %y tkTextSelectTo %W %x %y } bind Text { set tkPriv(selectMode) word tkTextSelectTo %W %x %y catch {%W mark set insert sel.first} } bind Text { set tkPriv(selectMode) line tkTextSelectTo %W %x %y catch {%W mark set insert sel.first} } bind Text { tkTextResetAnchor %W @%x,%y set tkPriv(selectMode) char tkTextSelectTo %W %x %y } bind Text { set tkPriv(selectMode) word tkTextSelectTo %W %x %y } bind Text { set tkPriv(selectMode) line tkTextSelectTo %W %x %y } bind Text { set tkPriv(x) %x set tkPriv(y) %y tkTextAutoScan %W } bind Text { tkCancelRepeat } bind Text { tkCancelRepeat } bind Text { %W mark set insert @%x,%y } bind Text { if {!$tkPriv(mouseMoved) || $tk_strictMotif} { tkTextPaste %W %x %y } } bind Text { tkTextSetCursor %W insert-1c } bind Text { tkTextSetCursor %W insert+1c } bind Text { tkTextSetCursor %W [tkTextUpDownLine %W -1] } bind Text { tkTextSetCursor %W [tkTextUpDownLine %W 1] } bind Text { tkTextKeySelect %W [%W index {insert - 1c}] } bind Text { tkTextKeySelect %W [%W index {insert + 1c}] } bind Text { tkTextKeySelect %W [tkTextUpDownLine %W -1] } bind Text { tkTextKeySelect %W [tkTextUpDownLine %W 1] } bind Text { tkTextSetCursor %W [%W index {insert - 1c wordstart}] } bind Text { tkTextSetCursor %W [%W index {insert wordend}] } bind Text { tkTextSetCursor %W [tkTextPrevPara %W insert] } bind Text { tkTextSetCursor %W [tkTextNextPara %W insert] } bind Text { tkTextKeySelect %W [%W index {insert - 1c wordstart}] } bind Text { tkTextKeySelect %W [%W index {insert wordend}] } bind Text { tkTextKeySelect %W [tkTextPrevPara %W insert] } bind Text { tkTextKeySelect %W [tkTextNextPara %W insert] } bind Text { tkTextSetCursor %W [tkTextScrollPages %W -1] } bind Text { tkTextKeySelect %W [tkTextScrollPages %W -1] } bind Text { tkTextSetCursor %W [tkTextScrollPages %W 1] } bind Text { tkTextKeySelect %W [tkTextScrollPages %W 1] } bind Text { %W xview scroll -1 page } bind Text { %W xview scroll 1 page } bind Text { tkTextSetCursor %W {insert linestart} } bind Text { tkTextKeySelect %W {insert linestart} } bind Text { tkTextSetCursor %W {insert lineend} } bind Text { tkTextKeySelect %W {insert lineend} } bind Text { tkTextSetCursor %W 1.0 } bind Text { tkTextKeySelect %W 1.0 } bind Text { tkTextSetCursor %W {end - 1 char} } bind Text { tkTextKeySelect %W {end - 1 char} } bind Text { tkTextInsert %W \t focus %W break } bind Text { # Needed only to keep binding from triggering; doesn't # have to actually do anything. } bind Text { focus [tk_focusNext %W] } bind Text { focus [tk_focusPrev %W] } bind Text { tkTextInsert %W \t } bind Text { tkTextInsert %W \n } bind Text { if {[%W tag nextrange sel 1.0 end] != ""} { %W delete sel.first sel.last } else { %W delete insert %W see insert } } bind Text { if {[%W tag nextrange sel 1.0 end] != ""} { %W delete sel.first sel.last } elseif [%W compare insert != 1.0] { %W delete insert-1c %W see insert } } bind Text { %W mark set anchor insert } bind Text