2 # Fubar plug-in to handle phonebook
4 if {![file exists ~/.phonebook.vcf]} {
5 error "Phonebook file $env(HOME)/.phonebook.vcf not found"
7 namespace eval phonebook {
8 # Returns true if phonebook was reread, false if it is not changed
10 proc read_phonebook {} {
12 variable phonebookstamp
13 if {[info exists phonebookstamp]&&[file mtime ~/.phonebook.vcf]<$phonebookstamp} {
16 if {[info exists phones]} {unset phones}
17 set f [open ~/.phonebook.vcf r]
18 fconfigure $f -encoding utf-8
20 while {[gets $f line]>=0} {
21 if {![string length $line]} continue
22 if {$state eq "photo"} {
23 if {![regexp ":" $line]} {
24 set index [lindex [array names cur_record "PHOTO*"] 0]
25 append cur_record($index) "$line\n"
31 foreach {field value} [split $line :] break
32 set list [split $field ";"]
33 if {[llength $list>1]} {
34 set field [lindex $list 0]
35 foreach opt [lrange $list 1 end] {
36 if {[string match CHARSET=* $opt]||
37 [string match ENCODING=* $opt]||
38 $opt eq "PREF"} continue
42 if {$field eq "END"} {
43 assemble_record cur_record
45 array unset cur_record
46 } elseif {$field eq "BEGIN"} {
47 if {[info exists currecord]} {
48 array unset cur_record
52 if {[string match "PHOTO*" $field]} {
53 set cur_record($field) "$value\n"
56 set cur_record($field) ""
57 foreach subval [split $value ";"] {
58 set cur_record($field) "$subval $cur_record($field)"
64 set phonebookstamp [clock seconds]
68 proc assemble_record {var} {
72 if [info exists record(ORG)] { append index ",$record(ORG)"}
73 if [info exists record(TITLE)] { append index ",$record(TITLE)"}
74 set phones($index) [array get record]
78 wm title $w "Phone book"
80 entry $w.search.pattern
81 button $w.search.loc -text "Find"\
82 -command [list ::phonebook::position $w]
83 button $w.search.filter -text "Filter"\
84 -command [list ::phonebook::filter $w]
85 button $w.search.new -text "New"\
86 -command [list ::phonebook::new_rec $w]
87 bind $w.search.pattern <Key-Return> [list $w.search.loc invoke]
88 bind $w.search.pattern <Control-Return> [list $w.search.filter invoke]
89 bind $w.search.pattern <Control-n> [list $w.search.new invoke]
90 pack $w.search.pattern -side left -fill x -expand y
91 pack $w.search.loc $w.search.filter $w.search.new -side left
92 listbox $w.list -yscrollcommand "$w.y set" -width 20
93 bind $w.list <<ListboxSelect>> "::phonebook::show_record $w \[%W get \[%W curselection\]\]"
94 bind $w.list <Key> [list ::phonebook::keyEvent $w.search.pattern %k %s %A %K]
95 scrollbar $w.y -orient vert -command "$w.list yview"
97 foreach {name title} {name "éÍÑ" org "ïÒÇÁÎÉÚÁÃÉÑ" title "ú×ÁÎÉÅ"
98 telcell "ôÅÌ. íÏÂ" telwork "ôÅÌ.òÁÂ." telhome "ôÅÌ.äÏÍ." telother
99 "ðÒÏÞÅÅ" fax "æÁËÓ" email "E-Mail"} {
100 label $w.record.l$name -text $title -anchor e
101 label $w.record.$name -anchor w
102 grid $w.record.l$name $w.record.$name -sticky news
104 label $w.record.image
105 button $w.record.edit -text Edit -command "::phonebook::edit_record"
106 button $w.record.mail -text Mail -state disabled -command "::phonebook::mail_to"
107 grid $w.record.image - -sticky news
108 grid $w.record.mail $w.record.edit -sticky ns
109 grid columnconfigure $w.record 1 -weight 1
110 grid columnconfigure $w.record 0 -weight 0
111 grid $w.search - - -sticky news
112 grid $w.list $w.y $w.record -sticky news
113 grid columnconfigure $w 0 -weight 1
114 grid columnconfigure $w 1 -weight 0
115 grid columnconfigure $w 2 -weight 1
117 proc keyEvent {window keycode state char keysym} {
118 if {![string length $char]} return;#ignore noncharacter keys
120 event generate $window <KeyPress> -keycode $keycode -keysym $keysym\
121 -state $state -when tail
123 proc show_record {w index} {
126 if {[info exists phones($index)]} {
127 array set record $phones($index)
131 if {[info exists current]} {unset current}
133 $w.record.name configure -text $record(N);
134 set_if_exists $w.record.org record(ORG)
135 set_if_exists $w.record.title record(TITLE)
136 set_if_exists $w.record.telcell "record(TEL CELL)"
137 set_if_exists $w.record.telhome "record(TEL HOME)"
138 set_if_exists $w.record.telwork "record(TEL WORK)"
139 set_if_exists $w.record.telother "record(TEL)"
140 set_if_exists $w.record.fax "record(TEL FAX)"
141 set_if_exists $w.record.email "record(EMAIL INTERNET)"
142 if {[info exists "record(EMAIL INTERNET)"]} {
143 $w.record.mail configure -state normal
145 $w.record.mail configure -state disabled
147 if {[llength [set img_index [lindex [array names record PHOTO*] 0]]]} {
148 if {![regexp {TYPE=([^[:space:]]+)} $img_index msg fmt]} {
151 $w.record.image configure -image [image create photo -format $fmt -data $record($img_index)]
153 $w.record.image configure -image ""
157 proc set_if_exists {w var} {
159 if {[info exists v]} {
160 $w configure -text $v
162 $w configure -text {}
166 proc fill_window {w} {
171 set list [lsort [array names phones]]
172 if {[info exists filter]} {
173 set list [lsearch -all -inline -regexp $list $filter ]
176 eval $w.list insert 0 $list
177 if {![info exists current]||[set index [lsearch -exact $list $current]]<0} {
180 $w.list selection clear 0 end
181 $w.list selection set $index
182 event generate $w.list <<ListboxSelect>>
183 after idle "$w.list see $index;focus $w.list"
184 focus $w.search.pattern
188 set pattern [$w.search.pattern get]
189 set list [$w.list get 0 end]
190 set index [lsearch -regexp $list $pattern]
192 $w.list selection clear 0 end
193 $w.list selection set $index
194 event generate $w.list <<ListboxSelect>>
195 after idle "$w.list see $index;focus $w.list"
201 set filter [$w.search.pattern get]
202 if {![string length $filter]} {
208 # Create an interface
210 if {$::argv0 ne [info script]} {
212 $m add command -label "Phone..." -command\
213 "create_or_raise .phonebook ::phonebook::mkwindow; ::phonebook::fill_window .phonebook"
215 button .b -text "Phonebook" -command "toplevel .phonebook;
216 ::phonebook::mkwindow .phonebook
217 ::phonebook::fill_window .phonebook"
225 array set r $phones($current)
226 if {![info exists "r(EMAIL INTERNET)"]} {
229 set address ${r(EMAIL INTERNET)}
230 exec $CONFIGDIR/mail $address &
239 proc edit_record {} {
247 proc edit_window {} {