2 # If we are not started from fubar
3 if {![info exists LIBRARYDIR]} {
4 set LIBRARYDIR [file dirname [info script]]
7 if {[file exists /proc/net/irda/discovery]} {
9 #variable discovery "/proc/net/irda/discovery"
10 variable discovery "/proc/net/irda/discovery"
11 variable config [file join $::CONFIGDIR irda.conf]
12 if {![file exists $config]} {
13 # create default config
14 file copy [file join $::LIBRARYDIR irda.conf] $config
16 #update interval in milliseconds
18 variable configread 0;#ensure config to be read on first update
20 variable menu $canvas.m
21 variable hintBits {0x100 PnP 0x200 PDA 0x400 Computer 0x800 Printer
22 0x1000 Modem 0x2000 Fax 0x4000 LAN 0x1 Telephony 0x2 FileServer
23 0x4 Comm 0x8 Message 0x10 Http 0x20 OBEX }
24 variable stdIcons {computer
25 {R0lGODlhEAAQAMIAAICAgMDAwAAAAP///wAA/////////////yH5BAEKAAcALAAAAAAQABAA
26 AANIeLrcDjDGF6qtQDAwuu+QtnBCaQ7hNghE26KZyroELCokXafj92WQkWlYAgREHJ/HGDuE
27 gAJoyig4WqtYTVLpOSqI4JJj7EgAADs=}
29 {R0lGODlhDgAOAMIAANPT02lpaQBkAP///////////////////yH5BAEKAAQALAAAAAAOAA4A
30 AAMySLrcBDDGwIC4WAC67PjYVmVhwD3ktZ2eMJRsqpmda6u0YqViJUGnhWlIZBCJPYeSkAAA
33 {R0lGODlhEAAQAKEAAAAAAKyqrL2+vf///yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAh+QQB
34 CgADACwAAAAAEAAQAAACLZyPCMm3zR40oE4XgoRA5510osZ5nQBSmSagzRig6TCecx3fZl6y
37 {R0lGODlhEAAQAKEAAI6KjgAAAP///////yH5BAEKAAIALAAAAAAQABAAAAInlI8pwKztmjKS
38 zgNQuGYff4GCqIjBiaYnN7IJycKcfGUu5biQfU8FADs=}
40 {R0lGODlhEAAQAOcAAAAAAAEBAQICAgMDAwQEBAUFBQYGBgcHBwgICAkJCQoKCgsLCwwMDA0N
41 DQ4ODg8PDxAQEBERERISEhMTExQUFBUVFRYWFhcXFxgYGBkZGRoaGhsbGxwcHB0dHR4eHh8f
42 HyAgICEhISIiIiMjIyQkJCUlJSYmJicnJygoKCkpKSoqKisrKywsLC0tLS4uLi8vLzAwMDEx
43 MTIyMjMzMzQ0NDU1NTY2Njc3Nzg4ODk5OTo6Ojs7Ozw8PD09PT4+Pj8/P0BAQEFBQUJCQkND
44 Q0REREVFRUZGRkdHR0hISElJSUpKSktLS0xMTE1NTU5OTk9PT1BQUFFRUVJSUlNTU1RUVFVV
45 VVZWVldXV1hYWFlZWVpaWltbW1xcXF1dXV5eXl9fX2BgYGFhYWJiYmNjY2RkZGVlZWZmZmdn
46 Z2hoaGlpaWpqamtra2xsbG1tbW5ubm9vb3BwcHFxcXJycnNzc3R0dHV1dXZ2dnd3d3h4eHl5
47 eXp6ent7e3x8fH19fX5+fn9/f4CAgIGBgYKCgoODg4SEhIWFhYaGhoeHh4iIiImJiYqKiouL
48 i4yMjI2NjY6Ojo+Pj5CQkJGRkZKSkpOTk5SUlJWVlZaWlpeXl5iYmJmZmZqampubm5ycnJ2d
49 nZ6enp+fn6CgoKGhoaKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq6ysrK2tra6urq+v
50 r7CwsLGxsbKysrOzs7S0tLW1tba2tre3t7i4uLm5ubq6uru7u7y8vL29vb6+vr+/v8DAwMHB
51 wcLCwsPDw8TExMXFxcbGxsfHx8jIyMnJycrKysvLy8zMzM3Nzc7Ozs/Pz9DQ0NHR0dLS0tPT
52 09TU1NXV1dbW1tfX19jY2NnZ2dra2tvb29zc3N3d3d7e3t/f3+Dg4OHh4eLi4uPj4+Tk5OXl
53 5ebm5ufn5+jo6Onp6erq6uvr6+zs7O3t7e7u7u/v7/Dw8PHx8fLy8vPz8/T09PX19fb29vf3
54 9/j4+Pn5+fr6+vv7+/z8/P39/f7+/v///yH5BAEKAP4ALAAAAAAQABAAAAhNAP0JFAigoMGC
55 AxMC+Mew4T8ACQk+PLgQYsSFDhtaVDjx4MOI/jBm/Hixo0GSHEeiJEixpUWXMAuqHClTZcWH
56 HWc6RBiTYkqaIHsODAgAOw==}
58 {R0lGODlhEAAQAMIAAICAgP///wAAAMDAwP///////////////yH5BAEKAAQALAAAAAAQABAA
59 AANISLoMznCBQB90juog5Azf1inTMGSiFJylOXAnUc4C4ApmRgO1e9a7Xs4BpJiEGKLQOEx2
60 cLlVkjciCKAsZcSK024X1+p3vEgAADs=}
63 variable iconUnknown {
64 R0lGODlhEAAQAIAAAAAAAP///yH5BAEKAAEALAAAAAAQABAAAAIgjA+px6bbEGAphtownZnb
65 /oGhNJLl5ZWamp4u+q5vUwAAOw==
68 # óÐÉÓÏË ÄÏÐÕÓÔÉÍÙÈ ÆÌÁÇÏ× ÚÎÁÞÅÎÉÅ 1 ÅÓÌÉ ÄÏÌÖÅÎ ÂÙÔØ ÐÁÒÁÍÅÔÒ
69 array set validFlags {
80 if {[file mtime $config]>$configread} {
83 set f [open $discovery]
84 while {[gets $f line]>=0} {
85 if {[string match "nickname:*" $line]} {
95 # schedules next update
99 after $poll ::irda::update
102 # ïÂÒÁÂÏÔËÁ ÐÕÓÔÏÇÏ discovery
103 # õÄÁÌÑÅÔ ×ÓÅ ÐÏÚÉÃÉÉ ÉÚ ÍÅÎÀ É ÕÄÁÌÑÅÔ ÉËÏÎËÕ
111 set hint "No IR device in range"
116 # ïÂÒÁÂÏÔËÁ ÎÁÊÄÅÎÎÏÇÏ ÕÓÔÒÏÊÓÔ×Á. ÷ÈÏÄÎÏÊ ÐÁÒÁÍÅÔÒ -
117 # ÓÔÒÏÞËÁ ÉÚ discovery
122 foreach field [split $line ","] {
123 if {[regexp {([a-z]+): +(.*)} $field xx name value]} {
124 set props($name) $value
128 if {![string match "$props(nickname)*" $hint]} {
129 foreach {bitMask prop} $hintBits {
130 if {$props(hint) & $bitMask} {
131 lappend propList $prop
134 set hint "$props(nickname) [join $propList ","]"
136 setup_icon $props(nickname) $propList
141 # ðÒÏ×ÅÒÑÅÔ ËÏÒÒÅËÔÎÏÓÔØ ÆÌÁÇÁ
143 proc checkFlag {name value file line} {
145 if {![info exists validFlags($name)]} {
146 error "Invalid flag `$name' at $file:$line"
148 if {$value && !$validFlags($name)} {
149 error "Flag $name shouldn't have a value at $file:$line"
151 if {!$value && $validFlags($name)} {
152 error "Flag $name shouldn have a value at $file:$line"
156 # þÔÅÎÉÅ ËÏÎÆÉÇÕÒÁÃÉÏÎÎÏÇÏ ÆÁÊÌÁ ÉÚ ÇÌÏÂÁÌØÎÏÊ ÐÅÒÅÍÅÎÎÏÊ
158 # ÇÌÏÂÁÌØÎÙÊ ÍÁÓÓÉ× confsections
162 variable confsections
164 set configread [clock seconds]
167 set qstr "(\"\[^\"]+\"|\[^ \t\]+)"
169 array unset confsections {}
170 set confsections(devices) {}
171 while {[gets $f line]>=0} {
173 if {![string length $line]} continue
174 if {[regexp "^\[ \t\]*#" $line]} continue
175 if {[regexp "^(\[A-Za-z\]\+):\[ \t\]*$" $line xx secname]} {
176 set secname [string tolower $secname]
177 set confsections($secname) {}
179 if {![info exists secname]} {
180 error "Syntax error in $config:$lineno - menu item without sectname"
182 if {$secname != "devices"} {
183 if {![regexp "\[ \t\]*$qstr$sp$qstr$sp\(.+)$" $line xx label flags cmd]} {
184 error "Syntax eror in $config:$lineno"
187 foreach flag [split [string trim $flags \"] ","] {
188 if {![string length $flag]} continue
189 if {[regexp {([^=]+)=(.*)} $flag xx name param]} {
190 checkFlag $name 1 $config $lineno
191 lappend flagList $name $param
193 checkFlag $flag 0 $config $lineno
194 lappend flagList $flag ""
197 lappend confsections($secname) [string trim $label \"] $flagList $cmd
199 if {![regexp "\[ \t\]*$qstr$sp(.*)" $line xx pattern filename]} {
200 error "Syntax error in $config:$lineno"
202 lappend deviceIcons $pattern filename
208 # ðÏËÁÚÙ×ÁÅÔ ÉËÏÎËÕ ÕÓÔÒÏÊÓÔ×Á. ðÁÒÁÍÅÔÒÙ nickname ÕÓÔÒÏÊÓÔ×Á
209 # É ÓÐÉÓÏË ÅÇÏ ÁÔÒÉÂÕÔÏ×.
210 proc setup_icon {name props} {
211 variable confsections
214 # óÎÁÞÁÌÁ ÉÝÅÍ ÓÐÅÃÉÆÉÞÅÓËÕÀ ÉËÏÎËÕ × ÓÅËÃÉÉ devices
215 foreach {pattern icon} $confsections(devices) {
216 if [string match $pattern $name] {
217 foreach path [list $::CONFIGDIR $::LIBRARYDIR] {
218 set fn [file join $path "icons" $name]
219 if [file exists $fn] {
224 # åÓÌÉ ËÁÒÔÉÎËÉ ÎÅ ÎÁÊÄÅÎÏ, ÐÒÅËÒÁÝÁÅÍ ÐÅÒÅÂÏÒ
228 set searchList [string tolower $props]
229 # åÓÌÉ ÎÅ ÎÁÊÄÅÎÏ, ÉÝÅÍ ÓÔÁÎÄÁÒÔÎÕÀ
230 foreach {device image} $stdIcons {
231 if {[lsearch -exact $searchList $device]!=-1} {
232 peer_image -data $image
236 # ÕÓÔÁÎÁ×ÌÉ×ÁÅÍ ÉËÏÎËÕ ÎÅÉÚ×ÅÓÔÎÏÇÏ ÕÓÔÒÏÊÓÔ×Á
237 peer_image -data $iconUnknown
241 # óÏÚÄÁÅÔ ÉËÏÎËÕ Ó ÔÜÇÏÍ peer ÎÁ ËÁÎ×Å.
243 proc peer_image {option value} {
245 $canvas create image 17 8 -anchor w -tag peer \
246 -image [image create photo $option $value]
249 # äÏÂÁ×ÌÑÅÔ × ÍÅÎÀ ÐÏÚÉÃÉÉ ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÉÅ Ó×ÏÊÓÔ×ÁÍ ÄÁÎÎÏÇÏ
250 # ÕÓÔÒÏÊÓÔ×Á É ÚÁÐÏÍÉÎÁÅÔ ÄÅÊÓÔ×ÉÑ, ËÏÔÏÒÙÅ ÓÌÅÄÕÅÔ ×ÙÐÏÌÎÉÔØ
251 # ÐÏ postcommand × ÐÒÏÃÅÄÕÒÅ show_menu
253 proc setup_menu {props} {
254 variable confsections
257 foreach prop [string tolower $props] {
258 if [info exists confsections($prop)] {
259 if {[$menu index end] > 0} {
262 foreach {name flags command} $confsections($prop) {
265 if {[info exists flg(pidfile)]} {
266 if {[string length $flg(pidfile)]} {
267 append checkCode [list check_pidfile $name $flg(pidfile) disable normal] "\n"
269 append checkCode [list check_process $name $command disable normal] "\n"
271 } elseif {[info exists flg(!pidfile)]} {
272 if {[string length $flg(!pidfile)]} {
273 append checkCode [list check_pidfile $name $flg(!pidfile) normal disable] "\n"
275 append checkCode [list check_process $name $command normal disable] "\n"
278 if {[info exists flg(gui)]} {
279 set cmd [list ::launch_gui $name $flg(gui) $command]
280 } elseif {[info exist flg(show)]} {
281 set cmd [list ::irda::launch_log $name $command]
283 set cmd [list ::irda::launch_bacground $name $command]
285 $menu add command -label $name -command $cmd
289 proc show_menu {} "$checkCode"
293 # ðÒÏÃÅÄÕÒÙ ÉÓÐÏÌØÚÕÅÍÙÅ × postcommand
295 # ðÒÏ×ÅÒÑÅÔ ÓÕÝÅÓÔ×Ï×ÁÎÉÅ ÕËÁÚÁÎÎÏÇÏ ÆÁÊÌÁ. ÅÓÌÉ ÏÎ ÓÕÝÅÓÔ×ÕÅÔ
296 # ×ÙÓÔÁ×ÌÑÅÔ ÓÔÁÔÕÓ ÕÇÁÚÁÎÎÙÊ × ifexists ÉÎÁÞÅ - × ifnotexists
298 proc check_pidfile {item file ifexists ifnotexists} {
300 if {[file exists $file]} {
301 $menu entryconfig $item -state $ifexists
303 $menu entryconfig $item -state $ifnotexists
307 # ðÒÏ×ÅÒÑÅÔ ÓÕÝÅÓÔ×Ï×ÁÎÉÅ ÐÒÏÃÅÓÓÁ Ó ÕËÁÚÁÎÎÏÊ ËÏÍÁÎÄÏÊ ÓÔÒÏËÏÊ
309 proc check_process {item command ifexists ifnotexists} {
310 set f [open "|ps auxww" "r"]
311 while {[gets $f line]>=0} {
312 if {[string match *$command $line]} {
313 $menu entryconfig $item -state $ifexists
318 $menu entryconfig $item -state $ifnotexists
320 # ðÒÏÃÅÄÕÒÙ, ÉÓÐÏÌØÚÕÅÍÙÅ ÄÌÑ ÚÁÐÕÓËÁ ËÏÍÁÎÄ
321 # åÓÌÉ ÓÕÝÅÓÔ×ÕÅÔ ÏËÎÏ ÕËÁÚÁÎÎÏÇÏ ËÌÁÓÓÁ, ÄÅÌÁÅÔ ÅÍÕ raise
322 # ÉÎÁÞÅ - ×ÙÐÏÌÎÑÅÔ ËÏÍÁÎÄÕ
323 proc launch_gui {name class command} {
324 if [catch package require Fvwm] {
325 ::fvwm::getWindowList a
326 foreach {index value} [array get a "*,class"] {
327 if {$value == "$class"} {
328 set $id [lindex [split $index ","] 0]
329 ::fvwm::send Raise $id
330 ::fvwm::send Focus $id
335 launch_background $name $command
338 # úÁÐÕÓËÁÅÔ ËÏÍÁÎÄÕ ÎÁÐÒÁ×ÌÑÑ ÅÅ ×Ù×ÏÄ × ÏËÎÏ
340 proc launch_log {name command} {
341 set w [uniqueWindow .irda.log]
343 text $w.t -yscrollcomand "$w.s set" -width 80 -state disabled
344 scrollbar $w.s -command "$w.t yview" -orient vert
345 pack $w.t -side left -fill both -expand y
346 pack $w.s -side right -fill y -expand n
347 set f [open "|$command" r]
348 fconfigure $f -blocking no -buffering no
349 fileevent $f readable [list ::irda::logInput $f $w.t]
352 proc logInput {file window} {
354 if [catch {close $f} msg] {
355 set string "\n********** TERMINATED *******\n$msg"
357 set string "\n*********** FINISHED ***************\n"
362 $w configure -state normal
363 $w insert end $string
365 $w configure -state disabled
369 # úÁÐÕÓËÁÅÔ ËÏÍÁÎÄÕ × ÆÏÎÅ
371 proc launch_background {name command} {
372 set exec [expandFilename $name $command]
377 # ðÏÄÓÔÁ×ÌÑÅÔ ÉÍÑ ÆÁÊÌÁ. ÷ÏÚ×ÒÁÝÁÅÔ -code return
378 # ÅÓÌÉ ÐÏÌØÚÏ×ÁÔÅÌØ ÏÔËÁÚÁÌÓÑ ÏÔ ×ÙÂÏÒÁ
380 proc expandFilename {name command} {
381 if {![regexp -indices {%filename%} $command match]} {
382 #nothig to substitute
385 if {![string length [set filename [tk_openFile -title $name]][} {
389 return [eval string replace [list $command] $match [list $filename]]
392 #setting up an interface
393 canvas $canvas -width 32 -height 16
394 pack $canvas -side right
395 menu $menu -postcommand ::irda::show_menu
396 bind $canvas <1> "$menu post \[winfo rootx %W\] \[expr \[winfo rooty .\]+\[winfo height .\]\]"
397 $canvas create image 1 8 -anchor w -image [image create photo\
398 -data {R0lGODlhEAAQAIAAAAAAAP///yH5BAEKAAEALAAAAAAQABAAQAIojI8AGKr2XluJSskgnVkf
399 zHnX9lkL2IVptXouM4aOKdOiXbpo/q5gAQA7}]
401 # Hint window management
403 toplevel $canvas.hint
404 wm overrideredirect $canvas.hint y
405 wm withdraw $canvas.hint
406 label $canvas.hint.l -textvar ::irda::hint -font 6x10 -background yellow
407 pack $canvas.hint.l -side left
408 bind $canvas <Enter> ::irda::start_hint
409 bind $canvas <Leave> ::irda::cancel_hint
410 bind $canvas <Motion> ::irda::reset_hint
412 variable hint_after_id
413 set hint_after_id [after 1000 ::irda::show_hint]
415 proc cancel_hint {} {
416 variable hint_after_id
418 if [info exists hint_after_id] {
419 after cancel $hint_after_id
422 if {[wm state $canvas.hint]=="normal"} {
423 wm withdraw $canvas.hint
432 wm geometry $canvas.hint +[expr [winfo pointerx .]+2]+[expr [winfo pointery .]+2]
433 wm deiconify $canvas.hint