This file is indexed.

/usr/share/amsn/plugins/winks/winks.tcl is in amsn-data 0.98.9-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
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
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
namespace eval ::winks {
	
	variable plugin_path ""

	#----------------------------------------------------------------------------------
	# DeInit: free resources and unset winks capacity
	#----------------------------------------------------------------------------------
	proc DeInit { dir } {
		# unset tha winks arrays and destroy the menu
		global HOME
		variable winks_list
		variable winks_cache

		array unset winks_list
		array unset winks_cache
		::winks::WinksMenuDestroy 
		# unset the winks client cap 
		::MSN::setClientCap winks 0
		catch { ::MSN::changeStatus [::MSN::myStatusIs] }
		status_log "Winks plugin unloaded.\n" green
	}

	#----------------------------------------------------------------------------------
	# Init: bind events, load winks list, set config variables
	#----------------------------------------------------------------------------------
	proc Init { dir } {
		
		status_log "Loading Winks plugin...\n" green

		global HOME
		variable wink_unknown_thumbnail
		variable wink_readme_path
		variable cabextract_version "undef"
		variable plugin_path ""

		# this variables helps me to avoid playing two winks at the same time in a chatwindow
		variable winks_f_playing_in
		array unset winks_f_playing_in

		set plugin_path $dir

		# create the directory structure if it doesn't exists
		create_dir [file join "$HOME" winks]
		create_dir [file join "$HOME" winks cache]
		create_dir [file join "$HOME" winks cache tmp]
		
		# load winks arrays
		::winks::LoadWinks
		::winks::LoadCache
		# load language file		
		load_lang en [file join $dir "lang"]
		load_lang [::config::getGlobalKey language] [file join $dir "lang"]
	
		# register plugin events
		::plugins::RegisterPlugin Winks
		::plugins::RegisterEvent Winks WinkReceived ReceivedWink
		::plugins::RegisterEvent Winks chatwindowbutton AddWinksButton
		::plugins::RegisterEvent Winks DataCastPacketReceived ReceiveSomething
		::plugins::RegisterEvent Winks PacketReceived ReceiveSomething
		::plugins::RegisterEvent Winks OnConnecting OnConnecting

		# load plugin pixmaps
		::skin::setPixmap unknown_wink unknown_wink.png pixmaps [file join $dir pixmaps]
		::skin::setPixmap butwinks winksbut.png pixmaps [file join $dir pixmaps]
		::skin::setPixmap butwinks_hover winksbut_hover.png pixmaps [file join $dir pixmaps]
		# remind the unknown wink thumbnail
		set wink_unknown_thumbnail [file join "$dir" pixmaps "unknown_wink.png"]
		# remind the README.txt path
		set wink_readme_path [file join "$dir" "README.txt"]

		# set plugin configuration
		array set ::winks::config {
#				show_add_wink 1
#				close_on_leave 1
				use_extrac32 0
				cabextractor ""
				flashplayer ""
				flashplayerargs ""
				play_inmediatly 1
				play_embed 0
				notify_in_one_line 0
				#use_queque_in 1
				#use_queque_out 1
		}
		set ::winks::configlist [ list \
#				[list bool "[trans winks_show_add_new_wink_in_menu]" show_add_wink] \
#				[list bool "[trans winks_close_menu_on_mouse_leave]" close_on_leave] \
				[list str "[trans winks_cabextract_command]" cabextractor] \
				[list bool "[trans winks_use_extrac32]" use_extrac32] \
				[list str "[trans winks_swf_player_command]" flashplayer] \
				[list str "[trans winks_swf_player_arguments]" flashplayerargs] \
				[list bool "[trans winks_play_wink_immediatly_when_recived]" play_inmediatly] \
				[list bool "[trans winks_play_embed]" play_embed] \
				[list bool "[trans winks_notify_in_one_line]" notify_in_one_line] \
				#[list bool "[trans winks_use_queque_in]" use_queque_in] \
				#[list bool "[trans winks_use_queque_out]" use_queque_out] \
				[list ext "[trans help]" {ShowReadme}] \
		]
	
		# set the clientcap
		::MSN::setClientCap winks
		if { "[::MSN::myStatusIs]" != "HDN" && "[::MSN::myStatusIs]" != "FLN" } {
			::MSN::changeStatus [::MSN::myStatusIs] 
		}

		# load plugin configuration NOW
		if {[array names ::plugins::config Winks] != ""} {
			if {$::plugins::config(Winks) != ""} {
				array set ::winks::config $::plugins::config(Winks)
			}
		}	
	
		# find out what cab extractor should we use
		if { "$::winks::config(cabextractor)" == "" && ! $::winks::config(use_extrac32) } {
			GuessCabextractor "$dir"
			set ::plugins::config(Winks) [array get ::winks::config]
		} elseif { ! $::winks::config(use_extrac32) } {
			CheckCabextractVersion
			if {$cabextract_version == "undef" } {
				GuessCabextractor "$dir"
			}
		}
		
		# if there's no flash player configured yet
		if { "$::winks::config(flashplayer)" == "" } {
			GuessFlashplayer "$dir"
			set ::plugins::config(Winks) [array get ::winks::config]
		}
		
		::plugins::save_config
		status_log $::winks::config(flashplayer) 
		status_log "Winks Loaded OK.\n" green
	}

	#----------------------------------------------------------------------------------
	proc OnConnecting { event evpar } {
		# With the SVN version (current 0.98b) the clientcap is reset to 0 everytime you try to connect
		# so we need to set our clientcap here now...
		::MSN::setClientCap winks
	}


	#----------------------------------------------------------------------------------
	# GuessFlashplayer: finds out what flashplayer command should we use.
	#----------------------------------------------------------------------------------
	proc GuessFlashplayer { dir } {
		status_log "Guessing flashplayer..."
		# see if there's any gnash over there in the system

		if { ! [catch { exec "gnash" "--version" } ver]  } {
			status_log "gnash found in system path." green
			set ::winks::config(flashplayer) "gnash"
			set ::winks::config(flashplayerargs) "-1"
			# see if there's any gnash over there in the system
			status_log [string range "$ver" 0 11]
			if { [string range "$ver" 0 11] != "Gnash 0.7.2" } {
				set ::winks::config(play_embed) 1
			} else {
				set ::winks::config(play_embed) 0
			}
		} else {
			# see if there's any flash player in the plugin directory
			if { [OnWin] } {
				if {[file exists [file join $dir "gnash.exe"]]} {
					status_log "gnash found in plugin path." green
					set ::winks::config(flashplayer) [file join $dir "gnash.exe"]
					set ::winks::config(flashplayerargs) "-1"
				} elseif {[file exists [file join utils windows gnash gnash.exe]] } {
					status_log "gnash found in utils path." green
					set ::winks::config(flashplayer) [file join utils windows gnash gnash.exe]
					set ::winks::config(flashplayerargs) "-1"
				} elseif {[file exists [file join $dir "flashplayer.exe"]]} {
					status_log "flashplayer in plugin path." green
					set ::winks::config(flashplayer) [file join $dir "flashplayer.exe"]
					set ::winks::config(flashplayerargs) ""
				} else {
					status_log "No player found." red
					return 0
				}
			} else {
				if {[file exists [file join $dir "gnash"]]} {
					status_log "gnash found in plugin path." green
					set ::winks::config(flashplayer) [file join $dir "gnash"]
					set ::winks::config(flashplayerargs) "-1"
				} elseif {[file exists [file join $dir "flashplayer"]]} {
					status_log "flashplayer found in plugin path." green
					set ::winks::config(flashplayer) [file join $dir "flashplayer"]
					set ::winks::config(flashplayerargs) ""
				} else {
					status_log "No player found." red
					return 0
				}
			}
		}
		return 1
	}
	
	#----------------------------------------------------------------------------------
	# GuessCabextractor: finds out what cabextract command should we use.
	#----------------------------------------------------------------------------------
	proc GuessCabextractor { dir } {
		status_log "Guessing cabextractor..."
		# try first with extrac32 (for windows systems)
		if { ! [catch { exec "extrac32" } ver]  } {
			status_log "extrac32 found." green
			set ::winks::config(use_extrac32) 1
		} else {
			# see if cabextract is present in the system
			set ::winks::config(cabextractor) "cabextract"
			if { ! [CheckCabextractVersion] } {
				if {[OnMac] && [file exists [file join utils macosx "cabextract"]]} {
					set ::winks::config(cabextractor) [file join utils macosx "cabextract"]
					CheckCabextractVersion
					status_log "cabextract found in utils/macosx path." green

				} elseif {[file exists [file join $dir "cabextract"]]} {
					# ... see if there's one in the plugin directory
					set ::winks::config(cabextractor) [file join $dir "cabextract"]
					CheckCabextractVersion
					status_log "cabextract found in plugin path." green
				} else {
					set ::winks::config(cabextractor) ""
					status_log "No cabextractor found." red
				}
			} else {
				status_log "cabextract found in system path." green
			}
		}
	}
	
	#----------------------------------------------------------------------------------
	# CheckCabextractVersion: finds out what cabextract version do we have
	#                         for correct use of -F arguments
	#----------------------------------------------------------------------------------
	proc CheckCabextractVersion { } {
		variable cabextract_version
		if { ! [catch { exec "[FixBars $::winks::config(cabextractor)]" "-v" } ver]  } {
			if { "$ver" == "cabextract version 0.1" || "$ver" == "cabextract version 0.2" 
			  || "$ver" == "cabextract version 0.3" || "$ver" == "cabextract version 0.4" 
			  || "$ver" == "cabextract version 0.5" || "$ver" == "cabextract version 0.6" 
			  || "$ver" == "cabextract version 1.0" || "$ver" == "cabextract version 1.1" } {
				set cabextract_version "old"
			} else {
				set cabextract_version "new"
			}
			return 1
		} else {
			set cabextract_version "undef"
			return 0
		}
	}
	
	#----------------------------------------------------------------------------------
	# ShowReadme: Shows a help window with the content of README.txt
	#----------------------------------------------------------------------------------
	proc ShowReadme { } {
		variable wink_readme_path
		
		if {![file exists $wink_readme_path]} {
			status_log "Can't open \"$wink_readme_path\"." red
			msg_box "[trans winks_cant_open] README.txt"
			return
		}
				
		if { [winfo exists .wink_readme] } {
			raise .wink_readme
			return
		}

		toplevel .wink_readme
		wm title .wink_readme "Winks Plugin Help - README.txt"
		ShowTransient .wink_readme
		wm state .wink_readme withdrawn

		# show readme widget
		frame .wink_readme.middle
		frame .wink_readme.middle.list -class Amsn -borderwidth 0
		text .wink_readme.middle.list.text -background white -width 80 -height 10 -wrap word \
			-yscrollcommand ".wink_readme.middle.list.ys set" -font splainf
		scrollbar .wink_readme.middle.list.ys -command ".wink_readme.middle.list.text yview"
		pack .wink_readme.middle.list.ys -side right -fill y
		pack .wink_readme.middle.list.text -side left -expand true -fill both
		pack .wink_readme.middle.list -side top -expand true -fill both -padx 1 -pady 1

		# show close button
		frame .wink_readme.bottom -class Amsn
		button .wink_readme.bottom.close -text "[trans close]" -command "destroy .wink_readme"
		bind .wink_readme <<Escape>> "destroy .wink_readme"
		pack .wink_readme.bottom.close -side right
		
		pack .wink_readme.bottom -side bottom -fill x -pady 3 -padx 5
		pack .wink_readme.middle -expand true -fill both -side top

		#Insert the text from the file
		set id [open "$wink_readme_path" r]
		fconfigure $id

		.wink_readme.middle.list.text insert 1.0 [read $id]
		close $id

		.wink_readme.middle.list.text configure -state disabled

		update idletasks

		wm state .wink_readme normal
		set x [expr {([winfo vrootwidth .wink_readme] - [winfo width .wink_readme]) / 2}]
		set y [expr {([winfo vrootheight .wink_readme] - [winfo height .wink_readme]) / 2}]
		wm geometry .wink_readme +${x}+${y}
		moveinscreen .wink_readme 30

	}	

	#----------------------------------------------------------------------------------
	# GetAttrib: if cut a sub string (field value) from a piece of xml, or return an 
	#            empty string if the given key id not found
	#----------------------------------------------------------------------------------
	proc GetAttrib { list_data attrib { decoded 0 } } {
		set idx [lsearch $list_data "${attrib}=*"]
		if { $idx == -1 } { return "" }
		set temp [lindex $list_data $idx]
		# if there's more than one word, complete temp
		set temp2 $temp
		while { "[string index $temp2 end-1 ]" != "\"" && $idx != [llength $list_data]} {
			incr idx
			set temp2 [lindex $list_data $idx]
			set temp "$temp $temp2"
		}
		# crop the value and return it
		set temp [split $temp "\""]
		set temp [lindex $temp 1]
		if { $decoded == 0 } {
			return $temp
		} else {
			return [urldecode $temp]
		}
	}
	
	#----------------------------------------------------------------------------------
	# GetFirstAfterInNode: Looks for a field after another field in a node
	#----------------------------------------------------------------------------------
	proc GetFirstAfterInNode { text_data attrib1 attrib2 } {
		set id [string first $attrib1 "$text_data"]
		if { $id == -1 } {
			return ""
		}
		set temp [string range "$text_data" $id end]
		set $id [string first ">" "$temp"]
		if { $id != -1 } {
			set temp [string range "$temp" 0 $id]
		}
		set id [string first $attrib2 "$temp"]
		if { $id == -1 } {
			return ""
		}
		set temp [split [string range "$temp" $id end] "\""]
		return [lindex $temp 1]
	}
	
	#----------------------------------------------------------------------------------
	# FixMissingAttrib: if looks for the missing field in the given file and return it,
	#                   or the default value if it's not found
	#----------------------------------------------------------------------------------
	proc FixMissingAttrib { filename field default } {
		if { [file exists "$filename"] == 0 } { 
			status_log "Missing $filename" red
			return "$default"
		} else {
			set fd2 [open "$filename" r]
			fconfigure $fd2 -encoding utf-8
			set lista [split [read $fd2] " "]
			close $fd2
			set attrib [GetAttrib $lista "$field"]
			if { "$attrib" == "" } {
				return "$default"
			} else {
				return "$attrib"
			}
		}
	} 

	#----------------------------------------------------------------------------------
	# FindFileName: finds the correct file name for a given one
	#----------------------------------------------------------------------------------
	proc FindFileName { dir fil } {
		if { [file exists [file join $dir [string tolower $fil]]] } { return [file join $dir [string tolower $fil]] }
		if { [file exists [file join $dir [string toupper $fil]]] } { return [file join $dir [string toupper $fil]] }
		return [file join $dir $fil]
	}

	#----------------------------------------------------------------------------------
	# LoadWinks: read $HOME/winks/index.xml and put that information in winks_list 
	#----------------------------------------------------------------------------------
	proc LoadWinks { } {

		# reset winks array and winks menu
		global HOME
		variable winks_list
		array unset winks_list
		::winks::WinksMenuDestroy 
		set modified 0
		
		# open winks index
		if { [file exists [file join "$HOME" winks index.xml]] == 0 } { 
			return 
		}
		set fd [open [file join "$HOME" winks index.xml] r]
		set data [read $fd]
		close $fd
		
		# separate winks
		set lista [split $data "\n"]

		foreach data $lista {
			# check if the line is a wink
			set listb [split "$data" " "]
			set sha1d [GetAttrib $listb "sha1d"]
			if { "$sha1d" != "" } { 
				# read wink information
				set wink(sha1d) $sha1d
				set wink(name) [GetAttrib $listb "name" 1]
				set wink(swf) [GetAttrib $listb "swf" 1]
				set wink(cab) [GetAttrib $listb "cab" 1]
				set wink(img) [GetAttrib $listb "img" 1]
				set wink(stamp) [GetAttrib $listb "stamp"]
				set wink(sizex) [GetAttrib $listb "sizex"]
				set wink(sizey) [GetAttrib $listb "sizey"]
				# fix bugs in some fields
				if { [string index $wink(name) end] == "\x00" } { set wink(name) [string range $wink(name) 0 end-1] } 
				# fix missing information
				if { "$wink(sizex)" == "" } {
					set modified 1
					set wink(sizex) [FixMissingAttrib "[file join [file dirname $wink(swf)] content.xml]" "wink:sizex" "0"]
					set wink(sizey) [FixMissingAttrib "[file join [file dirname $wink(swf)] content.xml]" "wink:sizey" "0"]
				}
				if { "$wink(name)" == "" } {
					set modified 1
					set wink(name) [FixMissingAttrib "[file join [file dirname $wink(swf)] content.xml]" "wink:name" "[file rootname \"[file tail \"$wink(swf)\"]\"]"]
				}
				# add the wink to the list
				if { [file exists $wink(cab)] } {
					set winks_list($sha1d) [array get wink]
				} else {
					status_log "Winks Menu: Missing files: Dropped one wink: \"$wink(name)\"." red
				}
			}
		}
		
		if { $modified == 1 } { SaveWinks }
		status_log "Winks loaded: [expr {[llength [array names winks_list] ] }]\n" green

	}

	#------------------------------------------------------------------------------------
	# LoadCache: read $HOME/winks/cache/index.xml and put that information in winks_list 
	#------------------------------------------------------------------------------------
	proc LoadCache { } {
		
		# reset winks cache
		global HOME
		variable winks_cache
		array unset winks_cache
		set modified 0
		
		# open winks cache index
		if { [file exists [file join "$HOME" winks cache index.xml]] == 0 } { 
			return 
		}
		set fd [open [file join "$HOME" winks cache index.xml] r]
		set data [read $fd]
		close $fd
		
		# separate winks
		set lista [split $data "\n"]

		foreach data $lista {
			# check if the line is a wink
			set listb [split "$data" " "]
			set sha1d [GetAttrib $listb "sha1d"]
			if { "$sha1d" != "" } { 
				# read wink information
				set wink(sha1d) $sha1d
				set wink(name) [GetAttrib $listb "name" 1]
				set wink(swf) [GetAttrib $listb "swf" 1]
				set wink(cab) [GetAttrib $listb "cab" 1]
				set wink(img) [GetAttrib $listb "img" 1]
				set wink(stamp) [GetAttrib $listb "stamp"]
				set wink(sizex) [GetAttrib $listb "sizex"]
				set wink(sizey) [GetAttrib $listb "sizey"]
				# fix bugs in some fields
				if { [string index $wink(name) end] == "\x00" } { set wink(name) [string range $wink(name) 0 end-1] } 
				# fix missing information
				if { "$wink(sizex)" == "" } {
					set modified 1
					set wink(sizex) [FixMissingAttrib "[file join [file dirname $wink(swf)] content.xml]" "wink:sizex" "0"]
					set wink(sizey) [FixMissingAttrib "[file join [file dirname $wink(swf)] content.xml]" "wink:sizey" "0"]
				}
				if { "$wink(name)" == "" } {
					set modified 1
					set wink(name) [FixMissingAttrib "[file join [file dirname $wink(swf)] content.xml]" "wink:name" "[file tail \"$wink(swf)\"]"]
				}
				# add the wink to the list
				if { [file exists $wink(cab)] } {
					set winks_cache($sha1d) [array get wink]
				} else {
					status_log "Winks Cache: Missing files: Dropped one wink: \"$wink(name)\"." red
				}
				
			}
		}
		
		if { $modified == 1 } { SaveCache }
		status_log "Winks in cache: [expr {[llength [array names winks_cache] ] }]\n" green

	}

	#----------------------------------------------------------------------------------
	# SaveWinks: write winks_list in $HOME/winks/index.xml
	#----------------------------------------------------------------------------------
	proc SaveWinks { } {
		global HOME
		variable winks_list
	        set fileId [open [file join "$HOME" winks index.xml] "w"]
		foreach sha1d [array names winks_list] {
			array set wink $winks_list($sha1d)
			if { "$wink(swf)" != "none" } {
				puts $fileId "<Wink name=\"[urlencode $wink(name)]\" cab=\"[urlencode $wink(cab)]\" swf=\"[urlencode $wink(swf)]\" img=\"[urlencode $wink(img)]\" sizex=\"$wink(sizex)\" sizey=\"$wink(sizey)\" sha1d=\"$wink(sha1d)\" stamp=\"$wink(stamp)\" />"
			}
		}
	        close $fileId
	}

	#----------------------------------------------------------------------------------
	# SaveCache: write winks_list in $HOME/winks/index.xml
	#----------------------------------------------------------------------------------
	proc SaveCache { } {
		global HOME
		variable winks_cache
	        set fileId [open [file join "$HOME" winks cache index.xml] "w"]
		foreach sha1d [array names winks_cache] {
			array set wink $winks_cache($sha1d)
			if { "$wink(swf)" != "none" } {
				puts $fileId "<Wink name=\"[urlencode $wink(name)]\" cab=\"[urlencode $wink(cab)]\" swf=\"[urlencode $wink(swf)]\" img=\"[urlencode $wink(img)]\" sizex=\"$wink(sizex)\" sizey=\"$wink(sizey)\" sha1d=\"$wink(sha1d)\" stamp=\"$wink(stamp)\" />"
			}
		}
	        close $fileId
	}

	#----------------------------------------------------------------------------------
	# AddWinkButton: add the winks button to chat window
	#                - left click in wink button opens winks menu
	#                - unload the wink menu (for testing and debuging, force reload)
	#                - right click in wink button adds a new wink from an .mco file
	#----------------------------------------------------------------------------------
	proc AddWinksButton { event evpar } {
		
		upvar 2 $evpar newvar
			
		set buttonbar $newvar(bottom)		

		set winksbut $buttonbar.winksbut
                set window $newvar(window_name)
                set chatid [::ChatWindow::Name $window]
                set winks_f_playing_in($chatid) 0

		button $winksbut -image [::skin::loadPixmap butwinks] -relief flat -padx 0 \
			-background [::skin::getKey buttonbarbg] -highlightthickness 0 -borderwidth 0 \
			-highlightbackground [::skin::getKey buttonbarbg] -activebackground [::skin::getKey buttonbarbg] \
			-command "::winks::WinksMenu $window \[winfo pointerx $window\] \[winfo pointery $window\] [::ChatWindow::GetInputText $window] \"\" 0"
		pack $winksbut -side left -padx 0 -pady 0

		bind $winksbut <<Button2>> "::winks::WinksMenuDestroy"
		bind $winksbut  <<Button3>> "::winks::AddWinkFromMCO $window"
		bind $winksbut  <Enter> "$winksbut configure -image [::skin::loadPixmap butwinks_hover]"
		bind $winksbut  <Leave> "$winksbut configure -image [::skin::loadPixmap butwinks]"	
		#bind $winksbut  <<Button1>> "::winks::WinksMenu $window \[winfo pointerx $window\] \[winfo pointery $window\] [::ChatWindow::GetInputText $window] \"\" 0"
	}
	
	
	#----------------------------------------------------------------------------------
	# WinksMenuDestroy: unload the winks menu. That happend when winks_list change
	#----------------------------------------------------------------------------------
	proc WinksMenuDestroy { } {
		if { [winfo exists .winksSelector]} {destroy .winksSelector}
	}

	#----------------------------------------------------------------------------------
	# winksCreateMenu: make the winks menu with the information in index.xml
	#----------------------------------------------------------------------------------
	proc winksCreateMenu { } {
	
		variable winks_list

		set w .winksSelector

		if {[catch {[toplevel $w]} res]} {
			destroy $w
			toplevel $w
		}
		
		set winksNumber [expr {[llength [array names winks_list] ] }]

		# fixed icon size
		set smiw 52
		set smih 52
		
		#We want to keep a certain ratio:
		# cols/(rows+1) = 4/3
		# we know cols*rows>=winksNumber
		#This is the solution of solving that equation system
		set ratio [expr {4.0/3.0}]		
		set cols [expr {ceil(($ratio+sqrt(($ratio*$ratio)+4.0*$ratio*$winksNumber))/2.0)}]

		# that's fix is to see correctly the "Add new Wink..." label in other languages	
		if { $cols < 5 } { set cols 5 }

		set rows [expr {ceil(double($winksNumber) / $cols)}]

		set cols [expr {int($cols)}]
		set rows [expr {int($rows)}]
		
		set x_geo [expr {$smiw*$cols + 2} ]
		set y_geo [expr {$smih*$rows + 2} + 26 ]
		
		wm state $w withdrawn
		wm geometry $w ${x_geo}x${y_geo}
		wm title $w "[trans msn]"
		wm overrideredirect $w 1
		wm transient $w
		
		
		canvas $w.c -background white -borderwidth 0 -relief flat \
			-selectbackground white -selectborderwidth 0 
		pack $w.c -expand true -fill both
		
		set wink_num 0
		set wink_pos 0
		
		foreach sha1d [array names winks_list] {

			array set wink $winks_list($sha1d)

			if { "$wink(swf)" != "none" } {
				set img "0"
				catch { set img [image create photo $wink(name) -file "$wink(img)" -format cximage] }
				winksCreateInMenu $w.c $cols $rows $smiw $smih \
					$wink_num $wink_pos $wink(name) $wink(name) $img
			
				incr wink_pos
				incr wink_num
			}
		}

		# show the "add new wink button"
		label $w.c.new_but -text "[trans winks_add_new_wink]"  -background [$w.c cget -background] -font sboldf
		bind $w.c.new_but <Enter> [list $w.c.new_but configure -relief raised]
		bind $w.c.new_but <Leave> [list $w.c.new_but configure -relief flat]
		set ypos [expr {($rows)*$smih +13}]
		$w.c create window  0 $ypos -window $w.c.new_but -width [expr {$x_geo - 2}] -height 26 -anchor w

		# define how to close the menu (that's for compiz/baryl focus trouble)
		bind $w <Leave> "::smiley::handleLeaveEvent $w $x_geo $y_geo"
		#bind $w <Enter> "bind $w <Leave> \"bind $w <Leave> \\\"wm state $w withdrawn\\\"\""

	}
	
	#----------------------------------------------------------------------------------
	# winksCreateInMenu: add a wink button to the winks menu
	#----------------------------------------------------------------------------------
	proc winksCreateInMenu {w cols rows smiw smih wink_num wink_pos name symbol image} {
		variable winks_list
		catch {
			set resized [image create photo]
			$resized copy $image
			if {[image width $image] > 44 && [image height $image] > 44} {
				::picture::ResizeWithRatio $resized 44 44
							}
			label $w.$wink_num -image $resized -background [$w cget -background]
			bind $w.$wink_num <Destroy> "image delete $resized"
	
			$w.$wink_num configure -cursor hand2 -borderwidth 1 -relief flat
			
			#Bindings for raise/flat on mouse over
			bind $w.$wink_num <Enter> [list $w.$wink_num configure -relief raised]
			bind $w.$wink_num <Leave> [list $w.$wink_num configure -relief flat]

			#Tooltip
			if { [::config::getKey tooltips] } {set_balloon $w.$wink_num "$name"}
			set xpos [expr {($wink_pos % $cols)* $smiw}]
			set ypos [expr {($wink_pos / $cols) * $smih}]
			$w create window $xpos $ypos -window $w.$wink_num -anchor nw -width $smiw -height $smih
		}
	}


	#----------------------------------------------------------------------------------
	# WinksMenu: bind events to the winks menu and shows it
	#----------------------------------------------------------------------------------
	proc WinksMenu { window_name {x 0} {y 0} {text text} categ categnum} {

		set chatid [::ChatWindow::Name $window_name]

		variable winks_list
		
		set w .winksSelector
		
		if { ! [winfo exists $w]} { 
			winksCreateMenu
		}
		
		wm state $w normal
		set x [expr {$x - 15}]
		set y [expr {$y + 15 - [winfo height $w]}]
		wm geometry $w +$x+$y

		#It won't work on Windows without this
		update idletasks
		
		
		# It won't work on Windows without this
		raise $w
		
		set temp 0
		
		# add winks bindings
		foreach sha1d [array names winks_list] {
			
			array set wink $winks_list($sha1d)
				
			if { "$wink(swf)" != "none" } {
				set symbol [lindex $wink(name) 0]
				
				#This must be cached due to a race condition (if you double click
				#the winks menu for first time, the second click can launch
				#this procedure without all winks having been created
				catch { 
					bind $w.c.$temp <<Button1>> "wm state $w withdrawn; ::MSN::ChatQueue $chatid \[list ::winks::SendWink $window_name $wink(sha1d)]"
					bind $w.c.$temp <<Button2>> "::winks::PlayWink \"$wink(swf)\""
					bind $w.c.$temp <<Button3>> "wm state $w withdrawn; ::winks::EditWinkDialog $chatid \"$wink(sha1d)\""
				}
				incr temp
			}
		}
		bind $w.c.new_but <<Button1>> "wm state $w withdrawn; ::winks::AddWinkFromMCO $window_name"
		moveinscreen $w 5
		event generate $w <Enter>
	
	}

	#----------------------------------------------------------------------------------
	# EditWinkDialog: ask for new wink name, and also let you delete the wink
	#----------------------------------------------------------------------------------
	proc EditWinkDialog { chatid sha1d } {
			set w .editWink
			variable winks_list
			array set wink $winks_list($sha1d)
			if { [winfo exists .editWink]} {destroy .editWink}
			toplevel $w
			wm group $w .
			wm title $w "Edit Wink: $wink(name)"
		
			frame $w.fn
			label $w.fn.label -font sboldf -text "[trans winks_introduce_new_wink_name]"
			entry $w.fn.name -width 40 -bg #FFFFFF -font splainf
		
			frame $w.fb
			button $w.fb.del -text [trans "delete"] -command "::winks::DeleteWink $chatid \"$sha1d\""
			button $w.fb.ok -text [trans "rename"] -command "::winks::RenameWink $chatid \"$sha1d\""
			button $w.fb.play -text [trans "winks_play"] -command [list ::winks::PlayWink $wink(swf)]
			button $w.fb.cancel -text [trans cancel] -command "destroy $w"
			bind $w <<Escape>> "destroy $w"
		
			label $w.fn.icon -image [image create photo .addNewWinkImg -file $wink(img) -format cximage] 
	
			pack $w.fn.icon -side left -fill x -expand true
			pack $w.fn.label $w.fn.name -side left -fill x -expand true
			pack $w.fb.ok $w.fb.cancel -side right -padx 5
			pack $w.fb.play $w.fb.cancel -side right -padx 5
			pack $w.fb.del -side left -padx 5
		
			bind $w.fn.name <Return> "::winks::RenameWink $chatid \"$sha1d\""
			pack $w.fn $w.fb -side top -fill x -expand true -padx 5
			$w.fn.name insert 0 "$wink(name)"
			
			update
			
			catch {
				raise $w
				focus -force $w.fn.name
			}
			moveinscreen $w 50
	}

	#----------------------------------------------------------------------------------
	# RenameWink: called from EditWinkDialog, changes a wink name
	#----------------------------------------------------------------------------------
	proc RenameWink { chatid sha1d } {
		variable winks_list
		set wname [.editWink.fn.name get]
		array set wink $winks_list($sha1d)
		# if the name is empty, find a suitable one
		if { "$wname" == "" } {
			set wink(name) [FixMissingAttrib "[file join [file dirname $wink(swf)] content.xml]" "wink:name" "[file rootname \"[file tail \"$wink(swf)\"]\"]"]
		} else {
			set wink(name) $wname
		}
		# upadate wink information
		set winks_list($sha1d) [array get wink]
		::winks::WinksMenuDestroy
		SaveWinks
		msg_box "[trans winks_wink_renamed]"
		destroy .editWink
	}
	
	#----------------------------------------------------------------------------------
	# DeleteWink: called from EditWinkDialog, delete a wink from winks_list
	#----------------------------------------------------------------------------------
	proc DeleteWink { chatid sha1d } {
		global HOME
		variable winks_cache
		variable winks_list
		set wname [.editWink.fn.name get]
		array set wink $winks_list($sha1d)

		# relocate files in cache again
#		catch {
			set cab_folder [::md5::md5 $sha1d]
			if  { [file exists [file join "$HOME" winks cache $cab_folder]] } {
				file delete -force [file exists "$HOME" winks cache $cab_folder]
			}
			file rename -force [file dirname $wink(swf)] [file join "$HOME" winks cache $cab_folder]
			set wink(cab) [file join "$HOME" winks cache $cab_folder [file tail $wink(cab)]]
			set wink(swf) [file join "$HOME" winks cache $cab_folder [file tail $wink(swf)]]
			set wink(img) [file join "$HOME" winks cache $cab_folder [file tail $wink(img)]]
			status_log "Wink Moved to Cache." green
#		} errs
#		if { "$errs" != "" } {
#			status_log "While deleting wink: $errs" red
#		} 

		# update arrays
		set winks_cache($sha1d) [array get wink] 
		unset winks_list($sha1d)	
		SaveWinks
		SaveCache
		WinksMenuDestroy				

		status_log "Wink deleted from menu." green
		destroy .editWink

		msg_box "[trans winks_wink_deleted]"
		return

	}

	#----------------------------------------------------------------------------------
	# AddWinkFromMCO: lets you choos an MCO file. if its corrects adds this wink to 
	#                 cache and shows the dialog to preview it and to add it and add it 
	#                 to the winks menu
	#----------------------------------------------------------------------------------
	proc AddWinkFromMCO { window_name } {
		global HOME
		set chatid [::ChatWindow::Name $window_name]
		set mco_file [chooseFileDialog "" "" "" "" "open" [list [list "Messenger Content Objets" [list *.mco *.MCO]] ] ]
		if { "$mco_file" != "" } {
			if { [file exists "$mco_file"] == 0 } {
				msg_box "[trans winks_cant_open] $mco_file" 
				return 
			}
			
			
			# extract fisrt content.xml
			ExtractCab "$mco_file" "content.xml" [file join $HOME winks cache tmp]
			set filename [file join  "$HOME" winks cache tmp content.xml]
			if { [file exists "$filename"] == 0 } { 
				msg_box "[trans winks_cant_open] content.xml"
				return 
			}
			
			# read first content.xml information
			set fd1 [open "$filename" r]
			fconfigure $fd1 -encoding utf-8
			set data [read $fd1]
			set lista [split $data " "]
			close $fd1
			file delete $filename
			
			# verify that the object is a wink
			if { [string first "type=\"wink\"" "$data"] == "-1" } {
				msg_box "\n[trans winks_file_is_not_a_wink]"
				return 
			}
			
			# get mco information
			set wink(cab) [GetAttrib $lista "file"]
			set wink(stamp) [GetAttrib $lista "stamp"]
		
			# extract the cab file in temp folder
			set temp_folder [file join "$HOME" winks cache tmp]
			ExtractCab "$mco_file" "$wink(cab)" $temp_folder
			
			# get the sha1d 
			set filename [file join $temp_folder $wink(cab)]
			if { [file exists "$filename"] == 0 } { 
				amsn::WinWrite $chatid "\n[trans winks_cant_open] \"$filename\"." red 
				return 
			}
			set fd2 [open $filename r]
			fconfigure $fd2 -translation binary
			set data [read $fd2]
			close $fd2
			set wink(sha1d) [::base64::encode [binary format H* [::sha1::sha1 $data]]]
			
			# see if the wink is already in the winks menu
			variable winks_list
			foreach wsha1d [array names winks_list] {
				if { "$wink(sha1d)" == "$wsha1d" } {
					status_log "The wink is already in winks menu!" red
					msg_box "[trans winks_the_wink_is_already_in_winks_menu]"
					file delete "$filename"
					return
				}
			}
			
			# get md5 and create dir in cache folder 
			set cab_folder [::md5::md5 $wink(sha1d)]
			create_dir [file join "$HOME" winks cache $cab_folder]
			
			# extract and read the cab content
			ExtractCab "$filename" "*" [file join "$HOME" winks cache $cab_folder]
			# move cab file to the correct location 
			set wink(cab) [file join "$HOME" winks cache $cab_folder $wink(cab)]
			file rename -force "$filename" "$wink(cab)"
			
			# read cabs's content.xml file
			set filename [file join "$HOME" winks cache $cab_folder content.xml]
			if { [file exists $filename] == 0 } { 
				amsn::WinWrite $chatid "\n[trans winks_cant_open] content.xml(2)." red 
				return 
			}
			set fd3 [open $filename r]
			fconfigure $fd3 -encoding utf-8
			set data [read $fd3]
			set listb [split $data " "]
			close $fd3
			
			# get wink information
			set wink(img) [FindFileName [file join "$HOME" winks cache $cab_folder] [GetFirstAfterInNode $data "thumbnail" "file"]]
			set wink(swf) [FindFileName [file join "$HOME" winks cache $cab_folder] [GetFirstAfterInNode $data "animation" "file"]]
			set wink(sizex) [GetAttrib $listb "wink:sizex"]
			set wink(sizey) [GetAttrib $listb "wink:sizey"]
			# fix missing information
			if { "$wink(sizex)" == "0" } {
				set wink(sizex) 0
				set wink(sizey) 0
			}
			set wink(name) [GetAttrib $listb "wink:name"]
			if { "$wink(name)" == "" } {
				set wink(name) [file rootname [file tail "$wink(swf)"]]
			}
			
			# copy information to cache
			variable winks_cache
			set winks_cache($wink(sha1d)) [array get wink]
			SaveCache
			
			# show confirmation and name editing dialog
			AddWinkDialog $chatid $wink(sha1d) "$wink(img)" "$wink(swf)" "$wink(name)"
			
		}
		
	}


	#----------------------------------------------------------------------------------
	# AddWinkDialog: let you choose an .mco file and ask for a wink name for a new wink
	#----------------------------------------------------------------------------------
	proc AddWinkDialog { chatid sha1d img swf wname } {

		set w .addNewWink
		if { [winfo exists .addNewWink]} {destroy .addNewWink}
		toplevel $w
		wm group $w .
		wm title $w "[trans winks_add_new_wink]"
	
		frame $w.fn
		label $w.fn.label -font sboldf -text "[trans winks_introduce_new_wink_name]"
		entry $w.fn.name -width 40 -bg #FFFFFF -font splainf
	
		frame $w.fb
		button $w.fb.ok -text [trans ok] -command "::winks::AddWinkDialoOK $chatid $sha1d"
		button $w.fb.cancel -text [trans cancel] -command "destroy $w"
		button $w.fb.play -text [trans "winks_play"] -command [list ::winks::PlayWink $swf]
		bind $w <<Escape>> "destroy $w"

		label $w.fn.icon -image [image create photo .addNewWinkImg -file $img -format cximage] 
	
		pack $w.fn.icon -side left -fill x -expand true
		pack $w.fn.label $w.fn.name -side left -fill x -expand true
		pack $w.fb.ok $w.fb.cancel -side right -padx 5
		pack $w.fb.play -side left -padx 5
	
		bind $w.fn.name <Return> "::winks::AddWinkDialoOK $chatid $sha1d"
		pack $w.fn $w.fb -side top -fill x -expand true -padx 5

		$w.fn.name insert 0 "$wname"
	
		catch {
			raise $w
			focus -force $w.fn.name
		}
		moveinscreen $w 50
	}

	#----------------------------------------------------------------------------------
	# AddWinkDialoOK: change the wink name and moves it to winks menu 
	#----------------------------------------------------------------------------------
	proc AddWinkDialoOK { chatid sha1d } {
		variable winks_cache
		array set wink $winks_cache($sha1d)

		set wink_name [.addNewWink.fn.name get]
		if { "$wink_name" != "" } {
			set wink(name) "$wink_name"
			set winks_cache($sha1d) [array get wink]
		}
		destroy .addNewWink
		::winks::AddWinkFromCache $chatid $sha1d
	}

	#----------------------------------------------------------------------------------
	# PlayWink: call an external swf player to show the wink animation 
	#----------------------------------------------------------------------------------
	proc PlayWinkFromSHA1D { chatid sha1d } {
		
		variable winks_list
		variable winks_cache
		
		# see if the wink is in our winks menu to play it
		foreach wsha1d [array names winks_list] {
			if { "$sha1d" == "$wsha1d" } {
				array set wink $winks_list($sha1d)
				if { "$wink(img)" == "---unknown-wink---" } {
					msg_box "[trans winks_cant_play_now_wait_thumbnail]"
					return
				}
				if { $::winks::config(play_embed) } {
					::winks::PlayWinkInChatWindow "$wink(swf)" "$chatid" "$wink(sizex)" "$wink(sizey)"
				} else {
					::winks::PlayWink "$wink(swf)"
				}
				return
			}
		}

		# see if the wink is in our winks cache to play it
		foreach wsha1d [array names winks_cache] {
			if { "$sha1d" == "$wsha1d" } {
				array set wink $winks_cache($sha1d)
				if { "$wink(img)" == "---unknown-wink---" } {
					msg_box "[trans winks_cant_play_now_wait_thumbnail]"
					return
				}
				if { $::winks::config(play_embed) } {
					::winks::PlayWinkInChatWindow "$wink(swf)" "$chatid" "$wink(sizex)" "$wink(sizey)"
				} else {
					::winks::PlayWink "$wink(swf)"
				}
				return
			}
		}
		status_log "Wink not found: $sha1d" red
	}
	
	proc FixBars { path } {
		return [ string map {"\\" "\\\\"} [string map { "\\\\" "\\" } $path] ]
	}
	
	
	#----------------------------------------------------------------------------------
	# PlayWink: call an external swf player to show the wink animation.
	#           this is never played inside the chat window.
	#----------------------------------------------------------------------------------
	proc PlayWink { wfile } {

		# old play wink code
		status_log "Playing wink $wfile\n" green
		set command [concat "exec" "\"[FixBars $::winks::config(flashplayer)]\"" [split "$::winks::config(flashplayerargs)" " "] "\"$wfile\"" "&"]
		if {[catch { eval $command } errs] } {
			variable plugin_path
			if {[GuessFlashplayer $plugin_path] } {
				if {[catch { eval $command } errs] } {
					status_log "\nEval2: $command\n" red
					status_log "\nOutput: $errs\n" red
				}
			} else {
				status_log "\nEval: $command\n" red
				status_log "\nOutput: $errs\n" red
			}
		}
		
		return
	}

	#----------------------------------------------------------------------------------
	# PlayWink: play the wink inside the chatwindow. Only available for gnash.
	#----------------------------------------------------------------------------------
	proc PlayWinkInChatWindow { wfile chatid wkx wky } {

		variable winks_f_playing_in

		if {![OnLinux] } {
			return [PlayWink $wfile]
		}

		if { ![info exists winks_f_playing_in($chatid)] } {
			set winks_f_playing_in($chatid) 0
		}

		if { $winks_f_playing_in($chatid) } {
			return 
		}

		# say that we are playing something now
		set winks_f_playing_in($chatid) 1
		
		set win [[::ChatWindow::GetOutText [::ChatWindow::For $chatid] ] getinnerframe]
		
		# wait if the window isn't open yet
		while {! [winfo ismapped $win]} {
			update
		}
		
		# scale the animation size to window size keeping the aspect ratio
		set wny [winfo height $win]
		set wnx [winfo width $win]
		if { "$wkx" == "0" } {
			set sx $wnx
			set sy $wny
		} else { 
			if { $wky*$wnx/$wkx <= $wny } {
				set sx [expr { $wnx }]
				set sy [expr { $wky*$wnx/$wkx }]
			} else {
				set sy [expr { $wny }]
				set sx [expr { $wkx*$wny/$wky }]
			}
		}

		# create the widget where the animation will be played
		set outtext [[::ChatWindow::GetOutText [::ChatWindow::For $chatid]] getinnerframe]
		set outframe [winfo parent $outtext]
		set wink_text_pack [pack info $outtext]
 		pack forget $outtext 
		canvas $outframe.wink_canvas -background [::skin::getKey chat_input_back_color] -borderwidth 0 -relief solid -width $sx -height $sy
		eval pack $outframe.wink_canvas -in $outframe.padding -anchor center  -side top 
		
		# wait if the canvas isn't visible yet
		while {! [winfo ismapped $outframe.wink_canvas]} {
			update
		}
		
        	# play the animation
		status_log "Playing wink $wfile\n" green
		if {[catch { 	set io [open "|[FixBars $::winks::config(flashplayer)] -1 -x [winfo id $outframe.wink_canvas] -j $sx -k $sy $wfile" r] } ] } {
			variable plugin_path
			if {[GuessFlashplayer $plugin_path] } {
				if {[catch { 	set io [open "|[FixBars $::winks::config(flashplayer)] -1 -x [winfo id $outframe.wink_canvas] -j $sx -k $sy $wfile" r] } ] } {
					status_log "Couldn't launch the player"
					# delete the temp widget and show the text again
					destroy $outframe.wink_canvas
					eval pack $outtext $wink_text_pack
		
					# say that we finished playing
					set winks_f_playing_in($chatid) 0
					PlayWink $wfile
				}
			} else {
				status_log "Couldn't find proper player"
				# delete the temp widget and show the text again
				destroy $outframe.wink_canvas
				eval pack $outtext $wink_text_pack
		
				# say that we finished playing
				set winks_f_playing_in($chatid) 0
				PlayWink $wfile
			}
		}
		fconfigure $io -blocking 0
		gets $io line
		status_log "Read $line"
			
		while { ![eof $io] } { 
			after 1000
			update
			gets $io line
			status_log "Read $line"
		}
	
		# delete the temp widget and show the text again
		destroy $outframe.wink_canvas
		eval pack $outtext $wink_text_pack
		
		# say that we finished playing
		set winks_f_playing_in($chatid) 0
			
	}

	

	#----------------------------------------------------------------------------------
	# ExtractCab: extracts files from a .cab into some folder 
	#----------------------------------------------------------------------------------
	proc ExtractCab { cab_file pattern folder } {

		if {$::winks::config(use_extrac32)} {
			if { "$pattern" == "*" } { set pattern "/E" }
			catch { exec "extrac32" "/Y" "$cab_file" "$pattern" "/L" "$folder" } errs
			if { "$errs" != "" } { 
				status_log "cabextract output: $errs" 
			}	
		} else {

			# check cabextract version for correct use of -F arguments
			variable cabextract_version
			if { "$cabextract_version" == "undef" } {
				CheckCabextractVersion
			}	
		
			if { "$pattern" == "*" } {
				catch { exec "[FixBars $::winks::config(cabextractor)]" "$cab_file"  "-d" "$folder" "-q" } errs	
			} else {
				if { "$cabextract_version" == "old" } {
					catch { exec "[FixBars $::winks::config(cabextractor)]" "$cab_file" "-F" "$folder/$pattern" "-d" "$folder" "-q" } errs
				} else {
					catch { exec "[FixBars $::winks::config(cabextractor)]" "$cab_file" "-F" "$pattern" "-d" "$folder" "-q" } errs
				}	
			}
			if { "$errs" != "" } { 
				status_log "cabextract output: $errs" 
			}
		}
	}

	#----------------------------------------------------------------------------------
	# NotifyInChatWindow: write the message, the image and the link to play the wink 
	#----------------------------------------------------------------------------------
	proc NotifyInChatWindow	{ chatid sha1d wink_name texto { cache 0 } } {
		if {$::winks::config(notify_in_one_line)} {
			amsn::WinWrite $chatid "\n" green
			amsn::WinWriteIcon $chatid greyline 3
			amsn::WinWrite $chatid "\n[timestamp] ${texto} " green 
			WinWriteThumbnail "$chatid" "$sha1d" $cache
			amsn::WinWrite $chatid " \"$wink_name\".\n" green 
			amsn::WinWriteIcon $chatid greyline 3
		} else {
			amsn::WinWrite $chatid "\n[timestamp] ${texto}\n  " green 
			WinWriteThumbnail "$chatid" "$sha1d" $cache
			amsn::WinWrite $chatid "\n " green
			WinWritePlayLink "$chatid" "$sha1d" "$wink_name"
			amsn::WinWrite $chatid "\n" green
		}	
	}

	#----------------------------------------------------------------------------------
	# ReceiveSomething: when receives some message, checks if thats a wink. Then if 
	#                   the wink is in index.xml (see sha1d) plays it, if it's not 
	#                   there, ask for the cab file with an msnobject 
	#----------------------------------------------------------------------------------
	proc ReceiveSomething { event evpar } {

		global HOME
		variable winks_list
		variable winks_cache

		upvar 2 $evpar args
		upvar 2 $args(chatid) chatid
		upvar 2 $args(nick) nick
		upvar 2 $args(msg) msg
		
		set header "[$msg getHeader Content-Type]"
		set ID "[$msg getField ID]"
		
		if {$header == "text/x-msnmsgr-datacast" && $ID == "2"} {

			::ChatWindow::MakeFor $chatid
	
			#get the msnobj
			set data [$msg getBody]
			set lista [split $data " "]

			# extract the wink information from the msnobj
			set wink_name [FromUnicode [base64::decode [GetAttrib $lista "Friendly"]]]
			if { [string index $wink_name end] == "\x00" } { set wink_name [string range $wink_name 0 end-1] } 
 
			set sha1d [GetAttrib $lista "SHA1D"]
			set stamp [GetAttrib $lista "stamp"]
			set cab_file [GetAttrib $lista "Location"]
			set user [GetAttrib $lista "Creator"]

			status_log "Received Wink $wink_name $sha1d\n" green

			# see if the wink is in our winks menu to play it
			foreach wsha1d [array names winks_list] {
				if { "$sha1d" == "$wsha1d" } {
					array set wink $winks_list($sha1d)
					NotifyInChatWindow "$chatid" "$sha1d" "$wink(name)" "[::abook::getDisplayNick $user] [trans winks_yourcontact_winks]"
					if {$::winks::config(play_inmediatly)} {
						if { $::winks::config(play_embed) } {
							::winks::PlayWinkInChatWindow "$wink(swf)" "$chatid" "$wink(sizex)" "$wink(sizey)"
						} else {
							::winks::PlayWink "$wink(swf)"
						}
					}

					return
				}
			}

			# see if the wink is in our winks cache to play it
			foreach wsha1d [array names winks_cache] {
				if { "$sha1d" == "$wsha1d" } {
					array set wink $winks_cache($sha1d)
					NotifyInChatWindow "$chatid" "$sha1d" "$wink(name)" "[::abook::getDisplayNick $user] [trans winks_yourcontact_winks]" 1
					if {$::winks::config(play_inmediatly)} {
						if { $::winks::config(play_embed) } {
							::winks::PlayWinkInChatWindow "$wink(swf)" "$chatid" "$wink(sizex)" "$wink(sizey)"
						} else {
							::winks::PlayWink "$wink(swf)"
						}
					}

					return
				}
			}
			
			# if the wink is unknown ask for it

			# keep information about the wink
			set wink(name) "$wink_name"
			set wink(stamp) "$stamp"
			set wink(sha1d) "$sha1d"
			set wink(swf) "none"
			set wink(cab) "$cab_file"
			set wink(img) "---unknown-wink---"
			set winks_cache($sha1d) [array get wink]

			# request the msnobject
			set data [string range $data 13 [expr {[string first "stamp=" $data] -2 }] ]
			set data "$data/>"
			::MSNP2P::RequestObjectEx $chatid $user $data "wink"

			# notify 
			NotifyInChatWindow "$chatid" "$sha1d" "$wink(name)" "[::abook::getDisplayNick $user] [trans winks_yourcontact_winks]" 1
			status_log "asked for cab file\n" green	
		}
	}

	#----------------------------------------------------------------------------------
	# ReceiveWink: when an unknown wink cames, we ask for the cab file. This proc is 
	#              called when the cab file transfer is complete. It extracts the 
	#              content to a folder in cache and play its swf.
	#----------------------------------------------------------------------------------
	proc ReceivedWink { event evpar } {
		
		global HOME
		variable winks_cache

		upvar 2 $evpar args
		upvar 2 $args(chatid) chatid

		upvar 2 $evpar newvar
		set filename $newvar(filename)
    set chatid $newvar(chatid)
		
		status_log "Received wink file: $filename from $chatid\n" green

		# read the cab file
		set fd1 [open $filename r]
		fconfigure $fd1 -translation binary
		set data [read $fd1]
		close $fd1

		# get sha1d and the partial wink data we had
		set sha1d [::base64::encode [binary format H* [::sha1::sha1 $data]]]
		array set wink $winks_cache($sha1d)

		# get the cab content
		set cab_folder [::md5::md5 $sha1d]
		create_dir [file join "$HOME" winks cache "$cab_folder"] 
		set wink(cab) [file join "$HOME" winks cache $cab_folder $wink(cab)]
		file rename -force "$filename" "$wink(cab)"
		ExtractCab "$wink(cab)" "*" [file join "$HOME" winks cache $cab_folder]

		# read cabs's content.xml file
		set filename [file join "$HOME" winks cache $cab_folder content.xml]
		if { [file exists $filename] == 0 } { 
			amsn::WinWrite $chatid "\n[trans winks_cant_open] \"content.xml\"." red 
			return "" 
		}
		set fd1 [open $filename r]
		fconfigure $fd1 -encoding utf-8
		set data [read $fd1]
		close $fd1
		
		set lista [split $data " "]
		
		# get wink information
		set wink(img) [FindFileName [file join "$HOME" winks cache $cab_folder] [GetFirstAfterInNode $data "thumbnail" "file"]]
		set wink(swf) [FindFileName [file join "$HOME" winks cache $cab_folder] [GetFirstAfterInNode $data "animation" "file"]]
		set wink(sizex) [GetAttrib $lista "wink:sizex"]
		set wink(sizey) [GetAttrib $lista "wink:sizey"]

		# fix missing information
		if { "$wink(name)" == "" || "$wink(name)" == "Unused" } {
			set wink(name) [GetAttrib $lista "wink:name"]
			if { "$wink(name)" == "" } {
				set wink(name) [file rootname [file tail "$wink(swf)"]]
			}
		}		
		if { "$wink(sizex)" == "" } {
			set wink(sizex) 0
			set wink(sizey) 0
		}

		set winks_cache($sha1d) [array get wink]

		SaveCache

		status_log "Wink added to cache succesfully.\n" reed

		set twTag "wink_[::md5::md5 $sha1d]"
		catch { image create photo $twTag -file $wink(img) -format cximage }

		# play the animation
		if {$::winks::config(play_inmediatly)} {
			if { $::winks::config(play_embed) } {
				::winks::PlayWinkInChatWindow "$wink(swf)" "$chatid" "$wink(sizex)" "$wink(sizey)"
			} else {
				::winks::PlayWink "$wink(swf)"
			}
		}
		
	}


	#-------------------------------------------------------------------------------------------
	# WinWritePlayLink: Write Play "winkname" in the chat window, and bind PlayWink on click.
	#-------------------------------------------------------------------------------------------
	proc WinWritePlayLink { chatid sha1d wink_name { cache 0 } } {
		set outText [::ChatWindow::GetOutText [::ChatWindow::For $chatid]]
		set twTag "wink_play_[::md5::md5 $sha1d]"
		$outText tag configure $twTag -foreground #000080 -font splainf -underline true
		$outText tag bind $twTag <Enter> "$outText tag conf $twTag -underline false; $outText conf -cursor hand2"
		$outText tag bind $twTag <Leave> "$outText tag conf $twTag -underline true; $outText conf -cursor xterm"
		$outText tag bind $twTag <<Button1>> "::winks::PlayWinkFromSHA1D \"$chatid\" \"$sha1d\""
		$outText roinsert end "[trans winks_play] \"$wink_name\"." $twTag
	}
	
	#-------------------------------------------------------------------------------------------
	# WinWriteThumbnail: Draws the wink thumbnail to let you play it again or add to your winks
	#-------------------------------------------------------------------------------------------
	proc WinWriteThumbnail { chatid sha1d { cache 0 } } {
		
		if { "$cache" == 1 } {
			variable winks_cache
			array set wink $winks_cache($sha1d)
		} else {
			variable winks_list
			array set wink $winks_list($sha1d)
		}

		set tw [::ChatWindow::GetOutText [::ChatWindow::For $chatid]]
		
		set twTag "wink_[::md5::md5 $sha1d]"

		set pos [[::ChatWindow::GetOutText [::ChatWindow::For $chatid]] index end-1c]

		if { [file exists $wink(img)] } {
			# if we have the thumbnail, show it
			set thumbnail [image create photo $twTag -file $wink(img) -format cximage]
		} else {
			# if we don't have the thumbnail yet, we'll show the "please wait..." one
			variable wink_unknown_thumbnail
			set thumbnail [image create photo $twTag -file "$wink_unknown_thumbnail" -format cximage]
		}

		set chars [string length $twTag]

		set posyx [split $pos "."]

		set endpos "[lindex $posyx 0].[expr {[lindex $posyx 1] + $chars}]"
	

		$tw tag configure smiley -elide true
		$tw tag add smiley $pos $endpos

		$tw tag bind $twTag <Enter> "$tw configure -cursor hand2"
		$tw tag bind $twTag <Leave> "$tw configure -cursor xterm"
		
		
		# left click menu: "play" and "add to winks menu option"
		set copyMenu "${tw}.copy_$twTag"
		if { ![winfo exists $copyMenu] } {
			menu $copyMenu -tearoff 0 -type normal
			$copyMenu add command -label "[trans winks_play_animation]" -command "::winks::PlayWinkFromSHA1D $chatid $sha1d"
			# "add to winks menu" is only for cache winks
			if { $cache == 1 } {
					$copyMenu add command -label "[trans winks_add_to_winks_menu]" -command "::winks::AddWinkFromCache $chatid $sha1d"
			}
			$tw tag bind $twTag <Enter> "$tw configure -cursor hand2"
			$tw tag bind $twTag <Leave> "$tw configure -cursor xterm"
			$tw tag bind $twTag <<Button1>> "tk_popup $copyMenu %X %Y"
		}

		
#		$tw tag bind $twTag <<Button1>> "::winks::PlayWink \"$wink(swf)\""
		if { $cache == 1 } {
			$tw tag bind $twTag <<Button3>> ""
		}

		set cosa [$tw image create $endpos -image $thumbnail -padx 0 -pady 0]
		$tw tag add $twTag $cosa
		$tw tag remove smiley $endpos

	}

	#----------------------------------------------------------------------------------
	# SendWink: Send a wink to the other client. (right click in winks menu) 
	#----------------------------------------------------------------------------------
	proc SendWink { window_name sha1d } {
		
		variable winks_list
		array set wink $winks_list($sha1d)

		set chatid [::ChatWindow::Name $window_name]

		# avoid multi-converstation bug
		if { "[::abook::getContactData $chatid clientid]" != "" } {
			# check if the other client support winks
			if { [::MSN::hasCapability [::abook::getContactData $chatid clientid] winks] == 0 } {
				amsn::WinWrite $chatid "\n[::abook::getDisplayNick $chatid] [trans winks_yourcontact_amsn_client_doesnt_supports_winks] " green 
				return
			}
		}

		status_log "Sending wink... $wink(cab) $chatid\n"

		#  read cab file
		if { [file exists $wink(cab)] == 0 } { 
			return "" 
			amsn::WinWrite $chatid "\n[trans winks_cant_open] \"$wink(cab)\"." red 
		}
		set fd [open $wink(cab) r]
		fconfigure $fd -translation binary
		set data [read $fd]
		close $fd

		#prepare wink name
		set friendly [::base64::encode [ToUnicode $wink(name)] ]

		#  build the msnobj
		set sbn [::MSN::SBFor $chatid]
		create_msnobj [::config::getKey login] 8 $wink(cab) $friendly
		set msnobj [create_msnobj [::config::getKey login] 8 $wink(cab) $friendly $wink(stamp)]
    set p2pmsnobj [::p2p::MSNObject parse $msnobj]
    $p2pmsnobj configure -data $data
    $::obj_stor publish $p2pmsnobj

		#  send chunks
		set maxchars 1202
		set sb [::MSN::SBFor $chatid]
		if { $sb == 0 } { return }
		set data "ID: 2\r\nData: $msnobj\r\n"
		set chunks [expr {int( [string length $data] / $maxchars) + 1 } ]
		for {set i 0 } { $i < $chunks } { incr i } {
			set chunk [string range $data [expr $i * $maxchars] [expr ($i * $maxchars) + $maxchars - 1]]
			set msg ""
			if { $i == 0 } {
				set msg "MIME-Version: 1.0\r\nContent-Type: text/x-msnmsgr-datacast\r\n"
				if { $chunks == 1 } {
					set msg "${msg}\r\n$chunk"
				} else { 
					set msgid "[format %X [myRand 4369 65450]][format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]]-[format %X [expr { int([expr {rand() * 1000000}])%65450 } ] + 4369]-[format %X [myRand 4369 65450]][format %X [myRand 4369 65450]][format %X [myRand 4369 65450]]"
					set msg "${msg}Message-ID: \{$msgid\}\r\nChunks: $chunks\r\n\r\n$chunk"
				}
			} else {
				set msg "${msg}Message-ID: \{$msgid\}\r\nChunk: $i\r\n\r\n$chunk"
			}
			set msglen [string length $msg]
	
			::MSN::WriteSBNoNL $sbn "MSG" "U $msglen\r\n$msg"
			
		}

		#  notify
		NotifyInChatWindow "$chatid" "$sha1d" "$wink(name)" "[trans winks_sent_wink]"
		status_log "Wink Sent.\n"

	}

	#----------------------------------------------------------------------------------
	# AddWinkFromCache: moves a wink from cache to the wink menu 
	#----------------------------------------------------------------------------------
	proc AddWinkFromCache { chatid sha1d } { 
		
		global HOME
		variable winks_cache
		variable winks_list
		
		# see if the wink is in our wink menu
		foreach wsha1d [array names winks_list] {
			if { "$sha1d" == "$wsha1d" } {
				status_log "The wink is already in winks menu!" red
				msg_box "[trans winks_the_wink_is_already_in_winks_menu]"
				return
			}
		}

		# see if the wink is in our cache
		foreach wsha1d [array names winks_cache] {
			if { "$sha1d" == "$wsha1d" } {
				array set wink $winks_cache($sha1d)
				
				# check if the wink transfer isn't still in progress
				if { "$wink(img)" == "---unknown-wink---" } {
					msg_box "[trans winks_cant_add_now_wait_thumbnail]"
					return
				}
	
				# relocate files out of cache
				catch {
					set cab_folder [::md5::md5 $sha1d]
					file rename -force [file dirname $wink(swf)] [file join "$HOME" winks $cab_folder]
					if { [file exists $wink(cab)] } {
						file rename -force $wink(cab) [file join "$HOME" winks $cab_folder [file tail $wink(cab)]]
					}
					set wink(cab) [file join "$HOME" winks $cab_folder [file tail $wink(cab)]]
					set wink(swf) [file join "$HOME" winks $cab_folder [file tail $wink(swf)]]
					set wink(img) [file join "$HOME" winks $cab_folder [file tail $wink(img)]]
				} errs
				if { "$errs" != "" } {
					status_log "While deleting wink: $errs" red
				} 

				# update memory arrays
				set winks_list($sha1d) [array get wink] 
				unset winks_cache($sha1d)	
				SaveWinks
				SaveCache
				WinksMenuDestroy				
				
				# notify
				status_log "Wink Added!" green
				msg_box "[trans winks_wink_added]"
				return
			}
		}
	
	}

}