TclApps Library Source Code
Check-in [f28b8a5f0a]
Not logged in
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Use PNG images if possible. Updated the winico images and move to plugin.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: f28b8a5f0aa4783051c29a009d84ab61db4d465a
User & Date: patthoyts 2009-05-23 08:10:16
Context
2009-05-24
13:50
Improve the response to subscription requests and display the roster in the user list with an option to hide this. check-in: b907fdeb7d user: patthoyts tags: trunk
2009-05-23
08:10
Use PNG images if possible. Updated the winico images and move to plugin. check-in: f28b8a5f0a user: patthoyts tags: trunk
08:01
Add the XMPP.org issuer check-in: 929584d5c5 user: patthoyts tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Added apps/tkchat/images/network-offline.png.

cannot compute difference between binary files

Added apps/tkchat/images/network-online.png.

cannot compute difference between binary files

Added apps/tkchat/images/roster_away.png.

cannot compute difference between binary files

Added apps/tkchat/images/roster_chat.png.

cannot compute difference between binary files

Added apps/tkchat/images/roster_disabled.png.

cannot compute difference between binary files

Added apps/tkchat/images/roster_dnd.png.

cannot compute difference between binary files

Added apps/tkchat/images/roster_online.png.

cannot compute difference between binary files

Added apps/tkchat/images/roster_xa.png.

cannot compute difference between binary files

Added apps/tkchat/images/z_away.gif.

cannot compute difference between binary files

Added apps/tkchat/images/z_chat.gif.

cannot compute difference between binary files

Added apps/tkchat/images/z_disabled.gif.

cannot compute difference between binary files

Added apps/tkchat/images/z_dnd.gif.

cannot compute difference between binary files

Added apps/tkchat/images/z_online.gif.

cannot compute difference between binary files

Added apps/tkchat/images/z_xa.gif.

cannot compute difference between binary files

Changes to apps/tkchat/tkchat.ico.

cannot compute difference between binary files

Changes to apps/tkchat/tkchat.tcl.

26
27
28
29
30
31
32

33
34
35
36
37
38
39
..
41
42
43
44
45
46
47
48
49






50
51
52
53
54
55
56
...
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
...
331
332
333
334
335
336
337






338
339
340
341
342
343
344
345
346

347
348
349
350
351
352
353
....
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
....
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
....
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
....
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
....
9214
9215
9216
9217
9218
9219
9220



9221
9222
9223
9224
9225
9226
9227
9228
9229
9230
9231
9232
9233
9234
9235
9236
9237
9238
9239
9240
9241
9242
9243
9244
9245
9246
9247
9248
9249
9250
9251
9252
9253
9254
9255
9256
9257
9258
9259
# packages into the CVS tree. Make sure we have the real location of 
# the script and not a link.
set script [file normalize [info script]]
while {[file type $script] eq "link"} {
    set script [file join [file dirname $script] [file readlink $script]]
}
set tkchat_dir [file dirname [file normalize $script]]

set auto_path [linsert $::auto_path 0 $tkchat_dir [file join $tkchat_dir lib]]

package require Tcl 8.4		; # core Tcl
package require Tk  8.4		; # core Tk
package require http 2		; # core Tcl
package require msgcat		; # core Tcl
package require textutil	; # tcllib 1.0
................................................................................
package require log		; # tcllib
package require base64		; # tcllib
package require uri             ; # tcllib

catch {package require tls}	  ; # tls (optional)
catch {package require choosefont}; # font selection (optional) 
catch {package require picoirc}   ; # irc client (optional)
catch {package require img::png}  ; # more image types (optional)
catch {package require img::jpeg} ; # more image types (optional)






 
package require sha1		; # tcllib
package require jlib		; # jlib
package require muc		; # jlib
package require disco           ; # jlib 

catch {package require khim}    ; # khim (optional)
................................................................................
    }
}

namespace eval ::tkchat {
    variable chatWindowTitle "The Tcler's Chat"

    variable HEADUrl {http://tcllib.cvs.sourceforge.net/*checkout*/tcllib/tclapps/apps/tkchat/tkchat.tcl?revision=HEAD}
    variable rcsid   {$Id: tkchat.tcl,v 1.466 2009/05/13 12:02:08 patthoyts Exp $}

    variable MSGS
    set MSGS(entered) [list \
	    "%user% has entered the chat!" \
	    "Out of a cloud of smoke, %user% appears!" \
	    "%user% saunters in." \
	    "%user% wanders in." \
................................................................................
    gGVZlmVZlmVZFiA1S4IcgGWBlmVZlmVZgNQAAAAIB2BZlmVZlmUBDQBalmUB
    CWBZlmVZlmUBC2BZlgUogGVZFmhZlmUBCWBZlgUwAAAAAAAAlgUggGVZIAAg
    QEVN0QAMgAUcgGUBFRAAURQ9AzCABWABlmUB1QREkGM8zmAUgGVZlgVQEwRC
    BgBAjmEUgGVZlgVQEQQZABAZRkEAFmhZlgVEEWQAAABARkEAlmVZFhBBjwEA
    IABERTEAlmVZFhA9jwMBQFQUwwBYlmWBlgUYRVEYBkEMA2BZlmVZlgUAAAAA
    AAACgGWFADs=
}






image create photo ::tkchat::img::link_connected -data {
    R0lGODlhEAAQAMIGAAAAADs6OoZwV9zCmf/hyP/79////////yH5BAEKAAcA
    LAAAAAAQABAAAAM7eLrc/vAMIeIahYgx4yBEUGSVQ4EBqJUHJRQCqsbAqd3h
    jLuTDG6uhS3AmbAYsQGRc2wwgxGoZUqtQhIAOw==
}
image create photo ::tkchat::img::link_disconnected -data {
    R0lGODlhEAAQAMIGAAAAADs6OoZwV9zCmf/hyP/79////////yH5BAEKAAcA
    LAAAAAAQABAAAANBeLrc/nAIAdkohKoh3SBEsBSYpkygSHzgdEyFkL5ySwBZ
    Hi5gPgmS2aoH1KB2E47E9FqJNhwm1PR7VCvYrHZ7SAAAOw==

}

# -------------------------------------------------------------------------

::msgcat::mcload [file join $tkchat_dir msgs]

# -------------------------------------------------------------------------
................................................................................
	    .txt mark set AddBookmark "end - 1 line linestart"
	    BookmarkToggle auto
	}
	incr MessageCounter
	set title "$MessageCounter - $chatWindowTitle"
	wm title . $title
	wm iconname . $title
	WinicoUpdate
    }
}

proc ::tkchat::ResetMessageCounter {} {
    if { [focus] != {} } {
	variable MessageCounter
	variable chatWindowTitle

	set MessageCounter 0
	set title $chatWindowTitle
	wm title . $title
	wm iconname . $title
	WinicoUpdate
    }
}

proc ::tkchat::InsertTimestamp { w nick mark timestamp {tags {}} } {
    # The nick argument is here, so we can display the local time for
    # each nick.
    if { $timestamp == 0 } {
................................................................................
    }
    # If we did a conversion, return a "break" code, ending event processing
    # for our triggering keystroke.
    return -code break
}

proc ::tkchat::CreateGUI {} {
    global Options
    variable chatWindowTitle
    variable useTile
    variable NS

    SelectTkStyle

    wm title . $chatWindowTitle
    wm withdraw .
    wm protocol . WM_DELETE_WINDOW [namespace origin quit]
    
    if {[catch {
        image create photo ::tkchat::img::Tkchat \
            -file [file join $::tkchat_dir tkchat48.png]
    }]} {
        image create photo ::tkchat::img::Tkchat \
            -file [file join $::tkchat_dir tkchat48.gif]
    }
    if {[info command ::tkchat::img::Tkchat] ne {}} {
        wm iconphoto . -default ::tkchat::img::Tkchat
    }
    catch { createFonts }
................................................................................
    foreach idx [array names Options Visibility,*] {
	set tag [string range $idx 11 end]
	.txt tag configure $tag -elide $Options($idx)
    }

    Hook add message [namespace origin IncrMessageCounter]
    BookmarkInit
    WinicoInit

    Hook run init

    if {$Options(UseProxy)} {
	if {$Options(ProxyHost) != "" && $Options(ProxyPort) != ""} {
            # nothing
	} elseif {[info exists ::env(http_proxy)]} {
................................................................................
	UserInfoSend $jid
    }
    destroy $dlg
    unset [namespace current]::$id
    unset UI
}

# -------------------------------------------------------------------------

# Windows taskbar support.
# At some point I want to support multiple icons for nochat/chat/alert.
#
proc ::tkchat::WinicoInit {} {
    if {[tk windowingsystem] eq "win32" &&
	![catch {package require Winico}]} {
	variable TaskbarIcon
	variable WinicoWmState [wm state .]

	set icofile [file join [file dirname [info script]] tkchat.ico]
	if {[file exists $icofile]} {
	    set TaskbarIcon [winico createfrom $icofile]
	    winico taskbar add $TaskbarIcon \
		    -pos 0 \
		    -text [wm title .] \
		    -callback [list [namespace origin WinicoCallback] %m %i]
	    bind . <Destroy> [namespace origin WinicoCleanup]
	}
    } else {
	proc ::tkchat::WinicoUpdate {} {return}
    }
}

proc ::tkchat::WinicoUpdate {} {
    variable MessageCounter
    variable TaskbarIcon

    if {[llength [info commands winico]] < 1} { return }
    if { $MessageCounter > 0 } {
	winico taskbar modify $TaskbarIcon \
		-pos 2 \
		-text "$MessageCounter - Tcl'ers chat"
    } else {
	winico taskbar modify $TaskbarIcon \
		-pos 0 \
		-text "Tcl'ers chat"
    }
}

proc ::tkchat::WinicoCleanup {} {
    variable TaskbarIcon
    winico taskbar delete $TaskbarIcon
}

proc ::tkchat::WinicoCallback {msg icn} {
    variable WinicoWmState
    switch -exact -- $msg {
	WM_LBUTTONDOWN {
	    if { [wm state .] eq "withdrawn" } {
		wm state . $WinicoWmState
		wm deiconify .
		focus .eMsg
	    } else {
		set WinicoWmState [wm state .]
		wm withdraw .
	    }
	}
    }
}

# -------------------------------------------------------------------------

proc ::tkchat::BookmarkInit {} {
    variable bookmark

    set bookmark(id) 0
    set bookmark(removed) 0
................................................................................
        default {
            tk_messageBox -icon error -title error -message "we shouldn't be here"
        }
    }
}

proc ::tkchat::createRosterImages {} {



    image create photo ::tkchat::roster::chat -data {
	R0lGODlhDgAKAMIAAAAAAP//gICAgP///4CAQACA/wBAgH9/fyH5BAEKAAcA
	LAAAAAAOAAoAAAMseAesy22FKda4F0hq8dDARFSA9ymAoEIsWhSG4czL+8a0
	a+M5YMOy3o9HSwAAOw==
    }
    image create photo ::tkchat::roster::online -data {
	R0lGODlhDgAKAMIAAAAAAP//gICAgICAQACA/wBAgP///////yH5BAEKAAcA
	LAAAAAAOAAoAAAMkeAes/itIAR+QgVZ1w9DbIozhQhBFEQLnmW5s+1axq9It
	ekMJADs=
    }
    image create photo ::tkchat::roster::away -data {
	R0lGODlhDgAKAOMAAAAAAAAA////gICAgP///4CAQACA/wBAgP//////////
	/////////////////////yH5BAEKAAgALAAAAAAOAAoAAAQ4ECFAJQo4WCD6
	uERIaFMnDIFIAGMpFKjIttNgp+usAYZxHLgQK8Dr+YCqnfF4yUiKvZ9lCmVO
	JREAOw==
    }
    image create photo ::tkchat::roster::dnd -data {
	R0lGODlhDgAKAOMAAAAAAP//gICAgP8AAICAQP///wCA/wBAgP//////////
	/////////////////////yH5BAEKAAgALAAAAAAOAAoAAAQ5ECFA5aTAgsDF
	HOCQTVwgAGGYbQFxDkVciBIg3Kg8r4ZxHKiUCNDr/YIgXvF3qUyKvoNlSlxK
	p5IIADs=
    }
    image create photo ::tkchat::roster::xa -data {
	R0lGODlhDgAKAOMAAAAAAP8AAP//gICAgP///4CAQACA/wBAgP//////////
	/////////////////////yH5BAEKAAgALAAAAAAOAAoAAAQ4ECFAJQo4WCD6
	uERIaFMnDIFIAGMpFKjIttNgp+usAYZxHLgQK8Dr+YCqnfF4yUiKvZ9lCmVO
	JREAOw==
    }
    image create photo ::tkchat::roster::disabled -data {
	R0lGODlhDgAKAMIGAAAAAD09PW9vb4CAQICAgP//gP///////yH5BAEKAAcA
	LAAAAAAOAAoAAAMkeAes/qtIAh+QhVZ1y9DbQozhIghBEALnmW5s+1axq9It
	ekMJADs=
    }
}

proc ::tkjabber::xmlSafe { str } {
    return [string map \
	    {& {&amp;} < {&lt;} > {&gt;} \" {&quot;} ' {&apos;}} $str]
}






>







 







<

>
>
>
>
>
>







 







|







 







>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
>







 







|












|







 







|










|


|







 







<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







>
>
>
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
..
42
43
44
45
46
47
48

49
50
51
52
53
54
55
56
57
58
59
60
61
62
...
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
...
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
....
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
....
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
....
6100
6101
6102
6103
6104
6105
6106

6107
6108
6109
6110
6111
6112
6113
....
6624
6625
6626
6627
6628
6629
6630






























































6631
6632
6633
6634
6635
6636
6637
....
9164
9165
9166
9167
9168
9169
9170
9171
9172
9173
9174



9175

















9176




9177




9178
9179
9180
9181
9182
9183
9184
# packages into the CVS tree. Make sure we have the real location of 
# the script and not a link.
set script [file normalize [info script]]
while {[file type $script] eq "link"} {
    set script [file join [file dirname $script] [file readlink $script]]
}
set tkchat_dir [file dirname [file normalize $script]]
set imgdir [file join $tkchat_dir images]
set auto_path [linsert $::auto_path 0 $tkchat_dir [file join $tkchat_dir lib]]

package require Tcl 8.4		; # core Tcl
package require Tk  8.4		; # core Tk
package require http 2		; # core Tcl
package require msgcat		; # core Tcl
package require textutil	; # tcllib 1.0
................................................................................
package require log		; # tcllib
package require base64		; # tcllib
package require uri             ; # tcllib

catch {package require tls}	  ; # tls (optional)
catch {package require choosefont}; # font selection (optional) 
catch {package require picoirc}   ; # irc client (optional)

catch {package require img::jpeg} ; # more image types (optional)

if {![package vsatisfies [package provide Tk] 8.6]} {
    catch {package require img::png}  ; # more image types (optional)
}
set have_png [expr {[package vsatisfies [package provide Tk] 8.6] \
                        || [package provide img::png] ne {}}]
 
package require sha1		; # tcllib
package require jlib		; # jlib
package require muc		; # jlib
package require disco           ; # jlib 

catch {package require khim}    ; # khim (optional)
................................................................................
    }
}

namespace eval ::tkchat {
    variable chatWindowTitle "The Tcler's Chat"

    variable HEADUrl {http://tcllib.cvs.sourceforge.net/*checkout*/tcllib/tclapps/apps/tkchat/tkchat.tcl?revision=HEAD}
    variable rcsid   {$Id: tkchat.tcl,v 1.467 2009/05/23 08:10:16 patthoyts Exp $}

    variable MSGS
    set MSGS(entered) [list \
	    "%user% has entered the chat!" \
	    "Out of a cloud of smoke, %user% appears!" \
	    "%user% saunters in." \
	    "%user% wanders in." \
................................................................................
    gGVZlmVZlmVZFiA1S4IcgGWBlmVZlmVZgNQAAAAIB2BZlmVZlmUBDQBalmUB
    CWBZlmVZlmUBC2BZlgUogGVZFmhZlmUBCWBZlgUwAAAAAAAAlgUggGVZIAAg
    QEVN0QAMgAUcgGUBFRAAURQ9AzCABWABlmUB1QREkGM8zmAUgGVZlgVQEwRC
    BgBAjmEUgGVZlgVQEQQZABAZRkEAFmhZlgVEEWQAAABARkEAlmVZFhBBjwEA
    IABERTEAlmVZFhA9jwMBQFQUwwBYlmWBlgUYRVEYBkEMA2BZlmVZlgUAAAAA
    AAACgGWFADs=
}
if {$have_png} {
    # PNG format images
    image create photo ::tkchat::img::link_connected -file $imgdir/network-online.png
    image create photo ::tkchat::img::link_disconnected -file $imgdir/network-offline.png
} else {
    # GIF format versions
    image create photo ::tkchat::img::link_connected -data {
        R0lGODlhEAAQAMIGAAAAADs6OoZwV9zCmf/hyP/79////////yH5BAEKAAcA
        LAAAAAAQABAAAAM7eLrc/vAMIeIahYgx4yBEUGSVQ4EBqJUHJRQCqsbAqd3h
        jLuTDG6uhS3AmbAYsQGRc2wwgxGoZUqtQhIAOw==
    }
    image create photo ::tkchat::img::link_disconnected -data {
        R0lGODlhEAAQAMIGAAAAADs6OoZwV9zCmf/hyP/79////////yH5BAEKAAcA
        LAAAAAAQABAAAANBeLrc/nAIAdkohKoh3SBEsBSYpkygSHzgdEyFkL5ySwBZ
        Hi5gPgmS2aoH1KB2E47E9FqJNhwm1PR7VCvYrHZ7SAAAOw==
    }
}

# -------------------------------------------------------------------------

::msgcat::mcload [file join $tkchat_dir msgs]

# -------------------------------------------------------------------------
................................................................................
	    .txt mark set AddBookmark "end - 1 line linestart"
	    BookmarkToggle auto
	}
	incr MessageCounter
	set title "$MessageCounter - $chatWindowTitle"
	wm title . $title
	wm iconname . $title
	catch {::tkchat::winico::Update}
    }
}

proc ::tkchat::ResetMessageCounter {} {
    if { [focus] != {} } {
	variable MessageCounter
	variable chatWindowTitle

	set MessageCounter 0
	set title $chatWindowTitle
	wm title . $title
	wm iconname . $title
	catch {::tkchat::winico::Update}
    }
}

proc ::tkchat::InsertTimestamp { w nick mark timestamp {tags {}} } {
    # The nick argument is here, so we can display the local time for
    # each nick.
    if { $timestamp == 0 } {
................................................................................
    }
    # If we did a conversion, return a "break" code, ending event processing
    # for our triggering keystroke.
    return -code break
}

proc ::tkchat::CreateGUI {} {
    global Options have_png
    variable chatWindowTitle
    variable useTile
    variable NS

    SelectTkStyle

    wm title . $chatWindowTitle
    wm withdraw .
    wm protocol . WM_DELETE_WINDOW [namespace origin quit]
    
    if {$have_png} {
        image create photo ::tkchat::img::Tkchat \
            -file [file join $::tkchat_dir tkchat48.png]
    } else {
        image create photo ::tkchat::img::Tkchat \
            -file [file join $::tkchat_dir tkchat48.gif]
    }
    if {[info command ::tkchat::img::Tkchat] ne {}} {
        wm iconphoto . -default ::tkchat::img::Tkchat
    }
    catch { createFonts }
................................................................................
    foreach idx [array names Options Visibility,*] {
	set tag [string range $idx 11 end]
	.txt tag configure $tag -elide $Options($idx)
    }

    Hook add message [namespace origin IncrMessageCounter]
    BookmarkInit


    Hook run init

    if {$Options(UseProxy)} {
	if {$Options(ProxyHost) != "" && $Options(ProxyPort) != ""} {
            # nothing
	} elseif {[info exists ::env(http_proxy)]} {
................................................................................
	UserInfoSend $jid
    }
    destroy $dlg
    unset [namespace current]::$id
    unset UI
}































































# -------------------------------------------------------------------------

proc ::tkchat::BookmarkInit {} {
    variable bookmark

    set bookmark(id) 0
    set bookmark(removed) 0
................................................................................
        default {
            tk_messageBox -icon error -title error -message "we shouldn't be here"
        }
    }
}

proc ::tkchat::createRosterImages {} {
    global imgdir have_png
    foreach type {chat online away dnd xa disabled} {
        if {$have_png} {
            image create photo ::tkchat::roster::$type -file $imgdir/roster_$type.png



        } else {

















            image create photo ::tkchat::roster::$type -file $imgdir/z_$type.gif




        }




    }
}

proc ::tkjabber::xmlSafe { str } {
    return [string map \
	    {& {&amp;} < {&lt;} > {&gt;} \" {&quot;} ' {&apos;}} $str]
}

Added apps/tkchat/tkchat_winico.tcl.


















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# Windows taskbar support.
# At some point I want to support multiple icons for nochat/chat/alert.
#

# TODO: deal with IncrMessageCOunter and ResetMessageCounter  and detach bookmark

if {[tk windowingsystem] ne "win32"} { return }
if {[catch {
    package require Winico
}]} {
    return
}

namespace eval ::tkchat::winico {
    variable version 1.0.0
}

proc ::tkchat::winico::InitHook {} {
    variable TaskbarIcon
    variable WinicoWmState [wm state .]

    set icofile [file join [file dirname [info script]] tkchat.ico]
    if {[file exists $icofile]} {
        set TaskbarIcon [winico createfrom $icofile]
        winico taskbar add $TaskbarIcon \
            -pos 0 \
            -text [wm title .] \
            -callback [list [namespace origin Callback] %m %i]
        bind . <Destroy> [namespace origin Cleanup]
    }
}

proc ::tkchat::winico::Update {} {
    variable ::tkchat::MessageCounter
    variable TaskbarIcon

    if {[llength [info commands winico]] < 1} { return }
    if { $MessageCounter > 0 } {
	winico taskbar modify $TaskbarIcon \
		-pos 2 \
		-text "$MessageCounter - Tcl'ers chat"
    } else {
	winico taskbar modify $TaskbarIcon \
		-pos 0 \
		-text "Tcl'ers chat"
    }
}

proc ::tkchat::winico::Cleanup {} {
    variable TaskbarIcon
    winico taskbar delete $TaskbarIcon
}

proc ::tkchat::winico::Callback {msg icn} {
    variable WinicoWmState
    switch -exact -- $msg {
	WM_LBUTTONDOWN {
	    if { [wm state .] eq "withdrawn" } {
		wm state . $WinicoWmState
		wm deiconify .
		focus .eMsg
	    } else {
		set WinicoWmState [wm state .]
		wm withdraw .
	    }
	}
    }
}

# -------------------------------------------------------------------------
::tkchat::Hook add init ::tkchat::winico::InitHook
package provide tkchat::winico $::tkchat::winico::version
# -------------------------------------------------------------------------