1#!/usr/local/bin/bash 2 3# ncid - Network Caller-ID client 4 5# Copyright (c) 2001-2020 6# John L. Chmielewski <jlc@users.sourceforge.net> 7# Steve Limkemann 8# Todd Andrews <tandrews@users.sourceforge.net> 9 10# This program is free software: you can redistribute it and/or modify 11# it under the terms of the GNU General Public License as published by 12# the Free Software Foundation, either version 3 of the License, or 13# (at your option) any later version. 14 15# This program is distributed in the hope that it will be useful, 16# but WITHOUT ANY WARRANTY; without even the implied warranty of 17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18# GNU General Public License for more details. 19 20# You should have received a copy of the GNU General Public License 21# along with this program. If not, see <http://www.gnu.org/licenses/>. 22 23# Lines beginning with # and ending in backslash are a trick to allow sh 24# to execute the lines and tclsh/wish to ignore them. 25 26# START OF LOCAL MODIFICATION SECTION 27# set PATH to include /usr/local/bin \ 28 PATH=$PATH:/usr/local/bin; export PATH 29# END OF LOCAL MODIFICATION SECTION 30 31# eliminate duplicate PATHS https://unix.stackexchange.com/questions/40749/remove-duplicate-path-entries-with-awk-command \ 32 PATH=$(printf %s "$PATH" | awk -v RS=: '!a[$0]++' | paste -s -d: -) 33 34# determine full path to tclsh and wish binaries 35# set TCLSH variable, FreeBSD will call it something like tclsh8.4 \ 36 TCLSH=`type tclsh | sed 's,.* \/,/,'` 37# set WISH variable, FreeBSD will call it something like wish8.4 \ 38 WISH=`type wish | sed 's,.* \/,/,'` 39 40# configuration file \ 41 CF=/etc/ncid/ncid.conf 42 43# check for config file and set GUI if not found \ 44 [ -f $CF ] || GUI=1 45 46# if $GUI not set, set GUI based on configuration file \ 47 [ "$GUI" == "" ] && GUI=`awk 'BEGIN {GUI = 1} /^ *#/ {next} \ 48 /^ *set *NoGUI/ {if ($3 == 0) {GUI = 0}} \ 49 END {print GUI}' $CF` 50 51# if GUI == 1, look for the --no-gui option, if found set GUI="0" \ 52 [ "$GUI" == "1" ] && for i in $*; do if [ "$i" = "--no-gui" ]; then GUI="0"; fi; done 53 54# if DISPLAY is not in the environment, set GUI="0" \ 55 [ -z "$DISPLAY" ] && GUI="0" 56 57# if wish found and $GUI == 1, look for wish and exec it \ 58 [ -n "$WISH" ] && [ "$GUI" == "1" ] && exec $WISH -f "$0" -- "$@" 59 60# if tclsh found and $GUI == 0, look for tclsh and exec it \ 61 [ -n "$TCLSH" ] && [ "$GUI" == "0" ] && exec $TCLSH "$0" "$@" 62 63# if tclsh found and wish not found, exec tclsh with the --no-gui option \ 64 [ -n "$TCLSH" ] && exec $TCLSH "$0" --no-gui "$@" 65 66# tcl or tk not found \ 67 echo "wish or tclsh not found in your \$PATH"; exit -1 68 69set DefaultHost 127.0.0.1 70set DefaultPort 3333 71set ConfigFile /usr/local/etc/ncid/ncid.conf 72set ImageDir /usr/share/ncid/images 73set Logo $ImageDir/ncid.gif 74set ThemeDir /usr/share/ncid/themes 75 76### global variables that can be changed by 77### command line options, the configuration file, the rcfile 78set AltDate 0 79 80### global variables that can be changed by 81### command line options, the configuration file 82set Hosts [list] 83set Delay 15 84set PIDfile "" 85set PopupTime 1 86set Verbose 0 87set NoGUI 0 88set CallOnRing 0 89set HostnameFlag 0 90set Ring 999 91set NoExit 0 92set WakeUp 0 93set ExitOn exit 94set CallLog 0 95set Country "US" 96set LogEnable 0 97set UnixLogDir $::env(HOME)/NCID/client 98set WinLogDir "logs" 99set UnixRCfile "$::env(HOME)/.ncid" 100set WinRCfile ".ncid" 101set UnixASfile "$::env(HOME)/.config/autostart/net.sourceforge.ncid.desktop" 102 103### global variables that can be changed by 104### command line options, the rcfile 105set Host "" 106set Port "" 107 108### global variables that can be changed by 109### the configuration file, the rcfile 110set DateSepar "/" 111 112### global variables that can only be changed by 113#### command line options 114set Module "" 115 116### global variables that can only be changed by 117#### the configuration file 118set ModDir /usr/share/ncid/modules 119set ModName "" 120set NoOne 0 121set YearDot 0 122set WrapLines "word" 123set DialPrefix "" 124set preClient_1_0 0 125set nameWidth 30 126set ClipboardPopup 1 127set ClipboardPopupTime 3 128 129### global variables that can only be changed by 130### the rcfile 131set clock 24 132set autoSave "off" 133set autoStart "off" 134set fontList "" 135set wmGeometry "" 136 137### global variables that are used as static variables 138set NightMode 0 139set ThemeName "day" 140set fgColor "" 141set fg2Color "" 142set bckColor "" 143set LogFile "" 144set LogChan "" 145set LogStatus "Log File: disabled" 146set LogDirLocation "" 147set oldHost $Host 148set oldPort $Port 149set oldDateSepar $DateSepar 150set oldAltDate $AltDate 151set oldAutoSave $autoSave 152set oldAutoStart $autoStart 153set oldClock $clock 154set Leading1 "Leave" 155set oldLeading1 $Leading1 156set DialLineID "" 157set display_line_num 0 158set awakened 0 159set Begin 0 160set End 0 161set DoingCallLog 0 162set waitMsg 0 163set mod_menu 0 164set multi 0 165set menuDisabled 0 166set labelWidth 4 167set dateWidth 10 168set timeWidth 5 169set lineIDWidth 16 170set nmbrWidth 20 171set mtypeWidth 5 172set fieldseparators 6 173# the alias width must be in the same position as the alias type 174set aliasTypes "NAMEDEP NAMEONLY NMBRDEP NMBRONLY NMBRNAME LINEONLY" 175set aliasWidths "$nameWidth $nameWidth $nmbrWidth $nmbrWidth $nmbrWidth $lineIDWidth" 176set aliasList "" 177set dtfile "/usr/share/applications/net.sourceforge.ncid.desktop" 178set countryCodes "DE FR HR SE UK US NONE" 179array set hup {} 180set HostIndex -1 181set SelAliasType "" 182set ChangeHostFlag 0 183set hupColor "" 184set ltColor "" 185set dateColor "" 186set timeColor "" 187set lineColor "" 188set nmbrColor "" 189set nameColor "" 190set mtColor "" 191set tvFgColor "" 192set tvBckColor "" 193set vhFgColor "" 194set vhBckColor "" 195set vhInsColor "" 196 197set LEVEL1 1 198set LEVEL2 2 199set LEVEL3 3 200set LEVEL4 4 201set LEVEL5 5 202set LEVEL6 6 203set LEVEL7 7 204set LEVEL8 8 205set LEVEL9 9 206 207set TypeGroups [list] 208set oldTypeGroups [list] 209 210set SelectedTypes {BLK 0 CID 0 HUP 0 MWI 0 OUT 0 PID 0\ 211 PUT 0 RID 0 WID 0 MSG 0 NOT 0} 212set oldSelectedTypes [list] 213set SelectedAllTypes {BLK 1 CID 1 HUP 1 MWI 1 OUT 1 PID 1\ 214 PUT 1 RID 1 WID 1 MSG 1 NOT 1} 215set SelectedCalls {BLK 1 CID 1 HUP 1 MWI 1 OUT 1 PID 1\ 216 PUT 1 RID 1 WID 1 MSG 0 NOT 0} 217set SelectedMessages {BLK 0 CID 0 HUP 0 MWI 0 OUT 0 PID 0\ 218 PUT 0 RID 0 WID 0 MSG 1 NOT 1} 219set SelectedSmartPhone {BLK 0 CID 0 HUP 0 MWI 0 OUT 0 PID 1\ 220 PUT 1 RID 0 WID 0 MSG 0 NOT 1} 221 222set LineIDGroups 0 223set oldLineIDGroups 0 224set DiscoveredLineIDs [list] 225set SelectedLineIDs [list] 226set oldSelectedLineIDs [list] 227 228# Global Variables 229set Interpreter [info nameofexecutable] 230set ServerOptions "" 231set Dialed 0 232set ServerOptLineIDS "" 233set svrLID "" 234set OptPmsg "" 235set delayedMsgs "" 236 237set ConfigFileHost "" 238set ConfigFilePort "" 239set ConfigFileoldHost "" 240set ConfigFileoldPort "" 241set ConfigFileHosts "" 242set ConfigFileHostIndex "" 243 244set ArgHost "" 245set ArgPort "" 246set ArgoldHost "" 247set ArgoldPort "" 248set ArgHosts "" 249set ArgHostIndex "" 250 251set RCfileHost "" 252set RCfilePort "" 253set RCfileoldHost "" 254set RCfileoldPort "" 255set RCfileHosts "" 256set RCfileHostIndex "" 257set RCfileThemeName "" 258 259set PortableDir "" 260 261set ScriptDir [file normalize [file dirname [info script]]] 262if {[file exists [file join $ScriptDir [file tail $ConfigFile]]]} { 263 set PortableDir $ScriptDir 264 set ConfigFile [file join $PortableDir [file tail $ConfigFile]] 265} 266 267if {$::tcl_platform(platform) == "unix"} {set LogDir $UnixLogDir 268} elseif {$::tcl_platform(platform) == "windows"} {set LogDir $WinLogDir} 269 270if {[file exists $ConfigFile]} { 271 # note: debug log has not been opened yet so logMsg is unavailable 272 source $ConfigFile 273 set delayedMsgs "Processed config file: $ConfigFile" 274 #deprecated warning will be given once the log file has been opened 275 if {$Hosts == ""} { 276 if {$Host != ""} { 277 set delayedMsgs \ 278 "$delayedMsgs\n***** Host: $Host\n***** WARNING: config file option 'Host' is deprecated, use 'Hosts'" 279 } 280 if {$Port != ""} { 281 set delayedMsgs \ 282 "$delayedMsgs\n***** Port: $Port\n***** WARNING: config file option 'Port' is deprecated, use 'Hosts'" 283 } 284 if {$Host != "" || $Port != ""} { 285 if {$Host == ""} { 286 set newhost $DefaultHost 287 } else {set newhost $Host} 288 if {$Port == ""} { 289 set newport $DefaultPort 290 } else {set newport $Port} 291 set Hosts "$newhost:$newport" 292 set delayedMsgs \ 293 "$delayedMsgs\n***** Hosts: $newhost:$newport" 294 } 295 } else { 296 if {$Host != ""} { 297 set delayedMsgs \ 298 "$delayedMsgs\n***** Host: $Host\n***** WARNING: using config file 'Hosts option, remove deprecated 'Host' option." 299 set Host "" 300 } 301 if {$Port != ""} { 302 set delayedMsgs \ 303 "$delayedMsgs\n***** Port: $Port\n***** WARNING: using config file 'Hosts' option, remove deprecated, 'Port' option." 304 set Port "" 305 } 306 } 307} else {set delayedMsgs "*** Config file Missing: $ConfigFile"} 308 309# if we're running in tclsh, force non-graphical 310if {[regexp {tclsh} $Interpreter]} {set NoGUI 1} 311 312set ConfigFileHost $Host 313set ConfigFilePort $Port 314set ConfigFileoldHost $ConfigFileHost 315set ConfigFileoldPort $ConfigFilePort 316set ConfigFileHosts $Hosts 317set ConfigFileHostIndex $HostIndex 318 319### Constants 320 321set CygwinBat /cygwin.bat 322 323set viewTextWidth 80 324 325# historyTextWidth must be increased by 1 character 326# $timeWidth will be included after config file sets $clock which can 327# cause it to change its value from 5 to 8 328set historyTextWidth [ expr $labelWidth + $dateWidth + $lineIDWidth + \ 329 $nmbrWidth + $nameWidth + $mtypeWidth + \ 330 $fieldseparators + 1 ] 331 332set linelabel [format "%-${lineIDWidth}.${lineIDWidth}s" "LINE ID"] 333set nmbrlabel [format "%-${nmbrWidth}.${nmbrWidth}s" "NUMBER"] 334set namelabel [format "%-${nameWidth}.${nameWidth}s" "NAME"] 335set mtypelabel [format "%-${mtypeWidth}.${mtypeWidth}s" "MTYPE"] 336 337# DATE field width is either 10 or 11 characters 338# TIME field width is either 5 or 8 characters 339# clock 24 & DateSepar . 340set lbl1 "TYPE |DATE |TIME |$linelabel|$nmbrlabel|$namelabel|$mtypelabel|" 341# clock 24 & DateSepar - 342set lbl2 "TYPE |DATE |TIME |$linelabel|$nmbrlabel|$namelabel|$mtypelabel|" 343# clock 24 & DateSepar / 344set lbl3 "TYPE |DATE |TIME |$linelabel|$nmbrlabel|$namelabel|$mtypelabel|" 345# clock 12 & DateSepar . 346set lbl4 "TYPE |DATE |TIME |$linelabel|$nmbrlabel|$namelabel|$mtypelabel|" 347# clock 12 & DateSepar - 348set lbl5 "TYPE |DATE |TIME |$linelabel|$nmbrlabel|$namelabel|$mtypelabel|" 349# clock 12 & DateSepar / 350set lbl6 "TYPE |DATE |TIME |$linelabel|$nmbrlabel|$namelabel|$mtypelabel|" 351# clock 24 & DateSepar . & YearDot 1 352set lbl7 "TYPE |DATE |TIME |$linelabel|$nmbrlabel|$namelabel|$mtypelabel|" 353# clock 12 & DateSepar . & YearDot 1 354set lbl8 "TYPE |DATE |TIME |$linelabel|$nmbrlabel|$namelabel|$mtypelabel|" 355 356if {$ModName != ""} { 357 if {[regexp {^.*/} $ModName]} { set Module "$ModName" 358 } else {set Module "$ModDir/$ModName"} 359} else {set Module ""} 360 361### global variables that are fixed 362set Count 0 363set ExecSh 0 364set Socket 0 365set Try 0 366set Version "XxXxX" 367#during development the version# is embedded in the file name 368#'tolower' and 'repeat' thwarts sed in Makefile 369if {[string tolower $Version] == [string repeat "x" 5]} {set Version [file tail [info script]]} 370 371set VersionIDENT "client ncid (NCID) $Version" 372set Usage {Usage: ncid [OPTS] [ARGS] 373 OPTS: [--no-gui] 374 [--alt-date | -A] 375 [--call-log | -c] 376 [--country-code <code> | -C <country code>] 377 [--delay <seconds> | -D <seconds>] 378 [--help | -h] 379 [--hostname-flag | -H] 380 [--log-enable <0-2> | -l <0-2>] 381 [--log-dir <dirname> | -L <dirname>] 382 [--module <module name> | -m <module name>] 383 [--noexit | -X] 384 [--pidfile <file> | -p <file>] 385 [--PopupTime <0-5> | -t <0-5>] 386 [--ring <0-9|-1|-2|-9> | -r <0-9|-1|-2|-9>] 387 [--verbose <1-9> | -v <1-9>] 388 [--version | -V] 389 [--wakeup | -W] 390 391 ARGS: [<IP_ADDRESS> | <HOSTNAME>] 392 [<PORT_NUMBER>]} 393 394set hostname [info hostname] 395regsub {([^.]*).*} $hostname {\1/ncid} LineName 396set VersionInfo "Client: ncid \[$hostname\] NCID $Version" 397 398set Author \ 399" 400Copyright © 2001-2020 401John L. Chmielewski 402" 403 404set Website "http://ncid.sourceforge.net" 405 406set labBLK "BLK: Blocked - blacklisted call blocked" 407set labCID "CID: Caller ID - incoming call" 408set labHUP "HUP: Hangup - blacklisted call hangup" 409set labMSG "MSG: Message - text message from a user or the server" 410set labMWI "MWI: Voicemail - one or more voicemail messages" 411set labNOT "NOT: Notice - a smartphone message notice" 412set labOUT "OUT: Out - outgoing call" 413set labPID "PID: Phone ID - Caller ID from a smartphone" 414set labPUT "PUT: Phone out call - outgoing Caller ID from a smartphone" 415set labRID "RID: Ring Back - rings back when called number is available" 416set labWID "WID: Call Waiting ID - Caller ID from call waiting" 417 418set labList \ 419" 420$labBLK 421$labCID 422$labHUP 423$labMSG 424$labMWI 425$labNOT 426$labOUT 427$labPID 428$labPUT 429$labRID 430$labWID 431" 432 433set fieldList \ 434" 435TYPE - call or message label 436DATE - date of call or message 437TIME - time of call or message 438LINE ID - telephone line label 439NUMBER - caller telephone number 440NAME - caller name 441MTYPE - message type 442" 443 444set viewHelp \ 445" 446Types: Shows all NCID line types. Those 447 not crossed out are those that may 448 or may not show up in the history 449 window. 450 451LineIDs: Shows all line identifications. 452 Those that are not crossed out 453 are those that show up in the 454 history window. 455" 456 457set serverHelp \ 458" 459\"Reload alias, blacklist and whitelist files\" menu entry: 460 Server reloads its Alias, Blacklist and Whitelist files. 461 462\"Update current call log\" menu entry: 463 Server replaces items in its cidcall.log file with 464 aliases in its ncidd.alias file. 465 466\"Update all call logs\" menu entry: 467 Server replaces items in its current cidcall.log file 468 and previous ones with aliases in its ncidd.alias file. 469 470\"Reread call log\" menu entry: 471 Server resends the cidcall.log file. 472 473Selecting a line in the history window will enable the alias, 474blacklist, whitelist and clipboard menu entries. If a modem 475is active, \"Dial Number Manually \" is enabled. If the line 476selected is all digits, \"Dial Number From History\" will also 477be enabled. 478 479You can remove a history window line selection by clicking 480on \"Send Message:\" or on a text line below it 481 482Once you modify the alias file you must: 483 * Reload alias, blacklist and whitelist files 484 * Update the current call log or all call logs 485 * Reread call log 486 487Once you modify the blacklist or whitelist file, you must: 488 * Reload alias, blacklist and whitelist files 489" 490 491######################################################################## 492# PROCEDURE DEFINITIONS # 493######################################################################## 494 495# display error message and exit 496proc exitMsg {code msg} { 497 global NoGUI LogChan 498 499 if {$LogChan != ""} { 500 set systemTime [clock seconds] 501 puts $LogChan "\[[clock format $systemTime -format "%m/%d %H:%M"]\] $msg" 502 } 503 504 if $NoGUI { 505 puts stderr $msg 506 } else { 507 wm withdraw . 508 option add *Dialog.msg.wrapLength 9i 509 option add *Dialog.msg.font "courier 12" 510 tk_messageBox -message $msg -icon error -type ok 511 } 512 exit $code 513} 514 515# platform, OS, etc. 516proc machine {which} { 517 # Observed values platform os osgui 518 # Windows 10: windows Windows NT win32 519 # Mac (native GUI): unix Darwin aqua 520 # Mac (XQuartz): unix Darwin x11 521 # AndroWish: unix Linux x11 522 # Fedora 25 cinnamon: unix Linux x11 523 # FreeBSD unix FreeBSD x11 524 525 switch $which { 526 platform { 527 if {$::sdltk_present && [expr [sdltk android]]} {return "android"} 528 if {$::sdltk_present && [expr [sdltk ischromebook]]} {return "chromebook"} 529 return $::tcl_platform(platform) 530 } 531 os { 532 if {$::sdltk_present && [expr [sdltk ischromebook]]} {return "Chrome OS"} 533 if {$::sdltk_present && [expr [sdltk android]]} {return "Linux"} 534 return $::tcl_platform(os) 535 } 536 osgui { 537 return [tk windowingsystem] 538 } 539 osname { 540 set osname [machine os] 541 if {$osname eq "Darwin"} {return "OS X"} 542 if {$osname eq "Chrome OS"} {return "Chromebook"} 543 if {$::sdltk_present && [expr [sdltk android]]} {return "Android"} 544 return $osname 545 } 546 model { 547 if {$::borg_present} { 548 array set temparray [borg osbuildinfo] 549 return $temparray(model) 550 } else {return "not available"} 551 } 552 } 553} 554 555# display the $Try attempt number to connect to ncidd 556proc tryCount {msg} { 557 global Count 558 global Delay 559 global Try 560 global Txt 561 global NoGUI 562 563 # If $Delay == 0, do not try to reconnect 564 if (!$Delay) {exit -1} 565 566 if $NoGUI { 567 set Once 0 568 puts -nonewline stderr $msg 569 after [expr $Delay*1000] set Once 1 570 vwait Once 571 } else { 572 set Count $Delay 573 while {$Count > 0} { 574 if {$Count == 1} { 575 set Txt "$msg Try $Try in $Count second." 576 } else { 577 set Txt "$msg Try $Try in $Count seconds." 578 } 579 set Once 0 580 set Count [expr $Count - 1] 581 after [expr 1000] set Once 1 582 vwait Once 583 } 584 } 585} 586 587# close connection to NCID server if open, then reconnect 588proc Reconnect {} { 589 global Socket 590 global Count 591 592 if $Count { 593 # already waiting to reconnect, force a retry 594 set Count 0 595 return 596 } 597 598 if {$Socket > 0} { 599 # close connection to server 600 flush $Socket 601 fileevent $Socket readable "" 602 close $Socket 603 set Socket 0 604 } 605 606 connectCID 607} 608 609# This catches a lot of errors! 610proc bgerror {mess} { 611 global errorInfo 612 global errorCode 613 614 exitMsg 1 "BGError: $mess\n$errorInfo\n$errorCode\n" 615} 616 617proc ncidInfo {} { 618 619set sysInfo1 \ 620" 621Windowing System: [string totitle [machine osgui]] 622Operating System: [machine osname] 623Platform : [string totitle [machine platform]] 624Theme : [string totitle $::ThemeName]" 625 626if {[file isdirectory $::ThemeDir]} { 627 set sysInfo2 "\nAddon Themes Dir: $::ThemeDir/" 628} else {set sysInfo2 ""} 629 630set sysInfo3 \ 631" 632Config File : $::ConfigFile 633Preference File : $::rcfile 634Wish Executable : $::Interpreter 635 Version [info patchlevel] 636[regsub {:} $::LogDirLocation { :}] 637[regsub {: } [regsub { } $::LogStatus { }] { :}] 638" 639 if {$sysInfo2 == ""} { 640 set sysinfo "$sysInfo1$sysInfo3" 641 } else { 642 set sysinfo "$sysInfo1$sysInfo2$sysInfo3" 643 } 644} 645 646proc getWidgetProps {verboseLevel verboseMsg widgetPath whichOptions} { 647 648 #if whichOptions is "all" then all properties are dumped 649 #otherwise, only options related to color, relief and text are dumped 650 651 logMsg $verboseLevel "$verboseMsg Current theme reported by ttk::style is: [ttk::style theme use]" 652 653 lmap c [$widgetPath configure ] { 654 if {[llength $c] == 2} continue; 655 set testvarname [lindex $c 0] 656 set doDump 1 657 if {$whichOptions != "all"} { 658 set doDump 0 659 if {[string match -nocase "*ground*" $testvarname] || [string match -nocase "*color*" $testvarname] |\ 660 [string match -nocase "*relief*" $testvarname] | [string match -nocase "*text*" $testvarname]} { 661 set doDump 1 662 } 663 } 664 if {$doDump} { 665 set val [$widgetPath cget $testvarname] 666 logMsg $verboseLevel "$verboseMsg $widgetPath [format "%-25.25s %s" "$testvarname" "$val"]" 667 } 668 } 669 670} 671 672# performs crude checks on host and port 673# https://www.appypie.com/faqs/what-characters-are-allowed-in-a-domain-name 674# The characters allowed in a domain name include letters (abc), numbers 675# (123), and dashes/hyphens (---). No spaces are allowed and the domain 676# name can't begin or end with dash/hyphen. 677proc checkHosts {} { 678 global Hosts 679 680 # Hosts = host:port [host:port] [...] 681 foreach hostport $Hosts { 682 lassign [split $hostport ":"] host port 683 if {[string length $host] < 4} { 684 exitMsg 8 "Network address too short: $host" 685 } elseif {![regexp {^[\w][\w.-]+$} $host]} { 686 exitMsg 8 "Network address has characters not allowed: $host" 687 } 688 if {[regexp {^.*-$} $host]} { 689 exitMsg 8 "Network address must not end in a dash: $host" 690 } 691 if {![regexp {^\d{4,5}$} $port]} { 692 exitMsg 9 "Network port must be 4 or 5 digits: $port" 693 } 694 } 695} 696 697proc getWindowProps {verboseLevel verboseMsg windowPath} { 698 699 foreach i {geometry manager name parent rootx rooty width height screenwidth screenheight vrootwidth vrootheight \ 700 vrootx vrooty x y} { 701 set val [winfo $i $windowPath] 702 logMsg $verboseLevel "$verboseMsg $windowPath [format "%-25.25s %s" "$i" "$val"] " 703 } 704 705} 706 707# Get data from CID server 708proc getCID {} { 709 global Module Host Port Socket NoGUI Try Verbose VersionInfo 710 global Ring CallOnRing 711 global cid label display_line_num DoingCallLog 712 global call Dialed lineID ServerOptLineIDS 713 global WakeUp wakened targetTime Begin End ClientJobResult waitMsg 714 global mod_menu argument menuDisabled 715 global CIDaliasType LineAliasType 716 global ServerOptions nmbrREQ 717 global hup bckColor 718 global TypeGroups SelectedTypes ChangeHostFlag 719 global LineIDGroups SelectedLineIDs DiscoveredLineIDs 720 721 # convert list to array 722 array set t_array $SelectedTypes 723 724 set msg {server connection closed} 725 set cnt 0 726 while {$cnt != -1} { 727 if {[eof $Socket] || [catch {set cnt [gets $Socket dataBlock]} msg]} { 728 # remove event handler 729 fileevent $Socket readable "" 730 close $Socket 731 set ServerOptions "" 732 if !$NoGUI { 733 if {$menuDisabled == 0} { 734 set menu .menubar.server 735 $menu entryconfigure Reload* -state disabled 736 $menu entryconfigure Update*current* -state disabled 737 $menu entryconfigure Update*all*call* -state disabled 738 $menu entryconfigure Reread* -state disabled 739 $menu entryconfigure Add/Modify* -state disabled 740 $menu entryconfigure Add*to*Blacklist* -state disabled 741 $menu entryconfigure Remove*from*Blacklist* -state disabled 742 $menu entryconfigure Add*to*Whitelist* -state disabled 743 $menu entryconfigure Remove*from*Whitelist* -state disabled 744 $menu entryconfigure Dial*Number* -state disabled 745 $menu entryconfigure Copy*to*Clipboard* -state disabled 746 set menuDisabled 1 747 } 748 } 749 set Try [expr $Try + 1] 750 tryCount "$Host:$Port - $msg\n" 751 connectCID 752 return 753 } 754 set Try 0 755 756 # get rid of non-printable characters at start/end of string 757 set dataBlock [string trim $dataBlock] 758 759 if {[string match 200* $dataBlock]} { 760 # output NCID server connect message 761 logMsg $::LEVEL1 $dataBlock 762 regsub {200 (.*)} $dataBlock {\1} dataBlock 763 if $NoGUI { 764 logMsg $::LEVEL1 "$VersionInfo\n$dataBlock" 765 set targetTime 0 766 } else { 767 set targetTime [expr [clock clicks -milliseconds] + 500] 768 displayCID "$VersionInfo\n$dataBlock" 1 769 } 770 } elseif {[string match 254* $dataBlock]} { 771 # NCID server sent start of call log message 772 if {!$NoGUI} { 773 set DoingCallLog 1 774 .vh configure -state normal 775 .vh insert 1.0 "\n\n\t\tReading the call log\n\n" 776 set Begin [clock clicks -milliseconds] 777 } 778 } elseif {[string match {25[0-3]*} $dataBlock]} { 779 # NCID server sent call log message 780 if !$NoGUI { 781 .vh delete 1.0 6.0 782 .vh yview moveto 1.0 783 .vh configure -state disabled 784 if {[lindex [.vh yview] 0] + [lindex [.vh yview] 1] == 1.0} { 785 grid remove .ys 786 } else { 787 grid .ys 788 } 789 } 790 set DoingCallLog 0 791 if {[regexp {250} $dataBlock]} { 792 # NCID server sent end of call log message 793 if {!$NoGUI} { 794 set DiscoveredLineIDs [lsort -dictionary $DiscoveredLineIDs] 795 if {$ChangeHostFlag == 1} { 796 logMsg $::LEVEL1 "$dataBlock - $display_line_num lines" 797 set SelectedLineIDs $DiscoveredLineIDs 798 write_rc_file "set SelectedLineIDs" "set SelectedLineIDs \"$SelectedLineIDs\"" 799 set ChangeHostFlag 0 800 } 801 } 802 } else {logMsg $::LEVEL1 "$dataBlock"} 803 set End [clock clicks -milliseconds] 804 set elapsed [expr $End - $Begin] 805 logMsg $::LEVEL2 "$display_line_num call history entries in $elapsed milliseconds" 806 } elseif {[string match 300* $dataBlock]} { 807 # NCID server sent end of startup message 808 if {$ServerOptions == ""} {set ServerOptions "\nnone"} 809 logMsg $::LEVEL1 $dataBlock 810 logMsg $::LEVEL2 "ServerOptions: [split [regsub -all {^\n| +} $ServerOptions {}] "\n"]" 811 if {!$NoGUI} {logMsg $::LEVEL3 "DiscoveredLineIDs: $DiscoveredLineIDs"} 812 continue 813 } elseif {[string match 400* $dataBlock]} { 814 # NCID server has sent text to be displayed 815 logMsg $::LEVEL1 $dataBlock 816 toplevel .reply -background $bckColor 817 wm title .reply "Server's Response" 818 grid [text .reply.text -yscrollcommand ".reply.ys set" -setgrid 1 \ 819 -font FixedFontP -height 8 -width 70] \ 820 -pady 1 -padx 1 -sticky nesw 821 grid [ttk::scrollbar .reply.ys -command ".reply.text yview"] \ 822 -column 1 -row 0 -sticky ns -pady 1 -padx 1 823 grid [ttk::button .reply.btn -text "OK" -command {destroy .reply}] \ 824 -pady 10 -columnspan 2 825 grid columnconfigure .reply 0 -weight 1 826 grid rowconfigure .reply 0 -weight 1 827 wm minsize .reply 25 4 828 bind .reply <Configure> { 829 if {[lindex [.reply.text yview] 0] + [lindex [.reply.text yview] 1] == 1.0} { 830 grid remove .reply.ys 831 } else { 832 grid .reply.ys 833 } 834 } 835 modal {.reply} 836 continue; 837 } elseif {[string match 401* $dataBlock]} { 838 # NCID server has sent text to be displayed, must ACCEPT or REJECT 839 logMsg $::LEVEL1 $dataBlock 840 toplevel .reply -background $bckColor 841 wm title .reply "Server's Response" 842 grid [text .reply.text -yscrollcommand ".reply.ys set" -setgrid 1 \ 843 -font FixedFontP -height 8 -width 70] \ 844 -pady 10 -padx 10 -sticky nesw 845 .reply.text insert 1.0 "\n\n\tUpdating call logs" 846 .reply.text configure -state disabled 847 grid [ttk::scrollbar .reply.ys -command ".reply.text yview"] \ 848 -column 1 -row 0 -sticky ns -pady 10 -padx 5 849 grid [ttk::frame .reply.fr] -pady 10 -padx 10 -columnspan 2 -row 1 850 ttk::button .reply.accept_btn -text "Accept" -state disabled -command { 851 global multi 852 853 if {$multi} { 854 set temp "S" 855 } else { 856 set temp "" 857 } 858 puts $Socket "WRK: ACCEPT LOG$temp" 859 flush $Socket 860 destroy .reply 861 } 862 ttk::button .reply.reject_btn -text "Reject" -state disabled -command { 863 global multi 864 865 if {$multi} { 866 set temp "S" 867 } else { 868 set temp "" 869 } 870 puts $Socket "WRK: REJECT LOG$temp" 871 flush $Socket 872 destroy .reply 873 } 874 grid .reply.accept_btn .reply.reject_btn -in .reply.fr -padx 25 875 grid columnconfigure .reply 0 -weight 1 876 grid rowconfigure .reply 0 -weight 1 877 wm minsize .reply 40 5 878 bind .reply <Configure> { 879 if {[lindex [.reply.text yview] 0] + [lindex [.reply.text yview] 1] == 1.0} { 880 grid remove .reply.ys 881 } else { 882 grid .reply.ys 883 } 884 } 885 showBusy "." .reply.text 886 modal {.reply} 887 continue; 888 } elseif {[string match 402* $dataBlock]} { 889 logMsg $::LEVEL1 $dataBlock 890 set ClientJobResult "" 891 } elseif {[string match 403* $dataBlock]} { 892 logMsg $::LEVEL1 $dataBlock 893 set mod_menu 1 894 } elseif {[string match 410* $dataBlock]} { 895 logMsg $::LEVEL1 $dataBlock 896 .reply.text configure -state normal 897 .reply.text delete end-1chars 898 .reply.text configure -state disabled 899 .reply.text see end 900 catch { 901 if {[lindex [.reply.text yview] 0] + [lindex [.reply.text yview] 1] == 1.0} { 902 grid remove .reply.ys 903 } else { 904 grid .reply.ys 905 } 906 } 907 catch { 908 .reply.accept_btn configure -state normal 909 .reply.reject_btn configure -state normal 910 } 911 continue 912 } elseif {[string match 411* $dataBlock]} { 913 logMsg $::LEVEL1 $dataBlock 914 if {$mod_menu} { 915 set mod_menu 0 916 continue 917 } 918 if {[string length $ClientJobResult] < 4} { 919 set ClientJobResult "Done." 920 } 921 if {$Dialed} { 922 # $Dialed == 2 when dial aborted 923 if {$Dialed == 1} { 924 .dial.close configure -state active 925 .dial.abort configure -state active 926 } 927 set Dialed 0 928 } else {.confirm.close configure -state active} 929 } elseif {[string match INFO:* $dataBlock]} { 930 logMsg $::LEVEL1 $dataBlock 931 if {$mod_menu} { 932 set menu .menubar.server 933 $menu entryconfigure Copy*to*Clipboard* -state normal 934 set temp [split $dataBlock " "] 935 set fileType [lindex $temp 1] 936 if {$fileType == "dial"} { 937 set dialarg [lindex $temp 2] 938 } else {set argument [lindex $temp 2]} 939 switch $fileType { 940 alias { 941 set CIDaliasType [lindex $temp 2] 942 set LineAliasType [lindex $temp 3] 943 $menu entryconfigure Add*Alias* -state normal 944 } 945 black { 946 $menu entryconfigure Add*Black* -state disabled 947 $menu entryconfigure Add*White* -state normal 948 $menu entryconfigure Remove*Black* -state normal 949 $menu entryconfigure Remove*White* -state disabled 950 } 951 white { 952 $menu entryconfigure Add*Black* -state disabled 953 $menu entryconfigure Add*White* -state disabled 954 $menu entryconfigure Remove*Black* -state disabled 955 $menu entryconfigure Remove*White* -state normal 956 } 957 neither { 958 $menu entryconfigure Add*Black* -state normal 959 $menu entryconfigure Add*White* -state normal 960 $menu entryconfigure Remove*Black* -state disabled 961 $menu entryconfigure Remove*White* -state disabled 962 } 963 dial { 964 if {$dialarg == "NODIAL"} { 965 $menu.dial entryconfigure From*History* -state disabled 966 } else { 967 $menu.dial entryconfigure From*History* -state normal 968 } 969 } 970 } 971 continue; 972 } 973 .reply.text configure -state normal 974 if {$waitMsg} { 975 set waitMsg 0 976 .reply.text delete 1.0 end 977 } 978 .reply.text insert end [string range [append dataBlock " \n"] 6 end] 979 .reply.text configure -state disabled 980 continue 981 } elseif {[string match RESP:* $dataBlock]} { 982 logMsg $::LEVEL1 $dataBlock 983 if ($Dialed) { 984 if {[string first "Pickup phone" $dataBlock 0] != -1} { 985 .dial.abort configure -state active 986 .dial.close configure -state active 987 } else { 988 regsub {.*Server modem ([\w\d\s]+) dialed.*$} $dataBlock {\1} svrLID 989 } 990 } 991 append ClientJobResult [string range $dataBlock 6 end] 992 append ClientJobResult "\n" 993 continue 994 } elseif {[string match RPLY:* $dataBlock]} { 995 logMsg $::LEVEL1 $dataBlock 996 set ClientJobResult [string range $dataBlock 6 end] 997 append ClientJobResult "\n" 998 destroy .dial 999 doRPLY 1000 } elseif {[string match OPT:* $dataBlock]} { 1001 set ServerOpt [string trim [string range $dataBlock 5 end]] 1002 if {[string first "LineIDS:" $ServerOpt 0] != -1} { 1003 regsub {^.*LineIDS: (.*)$} $ServerOpt {\1} ServerOptLineIDS 1004 if {!$NoGUI} { 1005 .menubar.server entryconfigure Dial*Number* -state normal 1006 } 1007 } 1008 logMsg $::LEVEL3 "Received Server Option: $ServerOpt" 1009 set ServerOptions "$ServerOptions\n$ServerOpt" 1010 } 1011 if {[set label [checkType $dataBlock]]} { 1012 if {$label == 3} { 1013 # CIDINFO (ring) line 1014 set ringinfo [getField RING $dataBlock] 1015 # must use $call($lineinfo) instead of $cid 1016 set lineinfo [getField LINE $dataBlock] 1017 if {!$NoGUI} { 1018 set status [processLineID "$lineinfo"] 1019 if {$LineIDGroups == 1 && $status != 1} {continue} 1020 } 1021 if {[array get call $lineinfo] != {}} { 1022 set CIDtype [lindex $call($lineinfo) 5] 1023 if {$ringinfo == -4} { 1024 if {!$NoGUI } { 1025 # get line from hup array and restore HUP color in GUI 1026 if {[catch {set displine $hup($lineinfo)} huperr]} { 1027 logMsg $::LEVEL1 "huperr" 1028 } else { 1029 # restore theme color to $CIDtype 1030 .vh configure -state normal 1031 .vh replace $displine.0 $displine.0+4c "$CIDtype:" lttag 1032 .vh configure -state disabled 1033 } 1034 } 1035 } elseif {$CallOnRing && $CIDtype == "CID"} { 1036 if {$Module != "" && ($Ring == $ringinfo || 1037 ($Ring == -9 && $ringinfo > 1))} { 1038 sendCID $call($lineinfo) 1039 logMsg $::LEVEL1 "$dataBlock" 1040 } else { logMsg $::LEVEL6 "$dataBlock" } 1041 } 1042 } else { 1043 logMsg $::LEVEL1 "Phone line label \"$lineinfo\" not found" 1044 } 1045 if {$WakeUp && $ringinfo == 1} { 1046 doWakeup 1047 set wakened 1 1048 } 1049 } elseif {$label == 4 || $label == 5} { 1050 # MSG (4), NOT (4) 1051 # MSGLOG (5), NOTLOG (5) 1052 set msg [formatMSG $dataBlock] 1053 if {!$NoGUI} { 1054 set status [processLineID "[lindex $msg 4]"] 1055 set thisTYPE [lindex $msg 5] 1056 if {$LineIDGroups == 1 && $status != 1} {continue} 1057 if {$TypeGroups == 1} {continue} 1058 if {$TypeGroups == 3 && !$t_array($thisTYPE)} {continue} 1059 if {$TypeGroups == 4 && !$t_array($thisTYPE)} {continue} 1060 } 1061 displayLog $msg 1 1062 if {$label == 4} { 1063 if {!$NoGUI} { 1064 displayCID "[lindex $msg 7]\n" 1 1065 doPopup 1066 } 1067 if {$Module != ""} { 1068 sendMSG $msg 1069 } 1070 } 1071 } elseif {$label == 1 || $label == 2} { 1072 # CID (1), HUP (1) OUT (1), RID (1) 1073 # BLK (2), MWI (2), PID (2), PUT(2), WID (2) 1074 if {$WakeUp} { 1075 if {!$wakened} { 1076 doWakeup 1077 } else {set wakened 0} 1078 } 1079 set cid [formatCID $dataBlock] 1080 if {!$NoGUI} { 1081 set status [processLineID "[lindex $cid 4]"] 1082 set thisTYPE [lindex $cid 5] 1083 if {$LineIDGroups == 1 && $status != 1} {continue} 1084 if {$TypeGroups == 2} {continue} 1085 if {$TypeGroups == 3 && !$t_array($thisTYPE)} {continue} 1086 if {$TypeGroups == 4 && !$t_array($thisTYPE)} {continue} 1087 } 1088 if {$label == 1} {array set call "{$lineID} [list $cid]"} 1089 # display log 1090 displayLog $cid 0 1091 # display CID 1092 if {!$NoGUI} { 1093 displayCID $cid 0 1094 doPopup 1095 } 1096 set CIDtype [lindex $cid 5] 1097 if {(!$CallOnRing || $CIDtype == "CID" || $Ring == -9) && $Module != ""} { 1098 sendCID $cid 1099 } 1100 } elseif {$label == 6} { 1101 # BLKLOG, CIDLOG, HUPLOG, MWILOG, OUTLOG, PIDLOG, PUTLOG, RIDLOG, WIDLOG 1102 set cid [formatCID $dataBlock] 1103 if {!$NoGUI} { 1104 set status [processLineID "[lindex $cid 4]"] 1105 set thisTYPE [lindex $cid 5] 1106 if {$LineIDGroups == 1 && $status != 1} {continue} 1107 if {$TypeGroups == 2} {continue} 1108 if {$TypeGroups == 3 && !$t_array($thisTYPE)} {continue} 1109 if {$TypeGroups == 4 && !$t_array($thisTYPE)} {continue} 1110 } 1111 # display log 1112 displayLog $cid 0 1113 if {!$NoGUI && $targetTime && [clock clicks -milliseconds] >= $targetTime} { 1114 set targetTime [expr [clock clicks -milliseconds] + 500] 1115 .vh insert 3.end "." 1116 update idletasks 1117 } 1118 } 1119 } 1120 } 1121 if {!$NoGUI && $DiscoveredLineIDs != ""} {updateViewDisplay} 1122} 1123 1124proc showBusy {text widget} { 1125 global waitMsg 1126 1127 $widget configure -state normal 1128 $widget insert end $text 1129 $widget configure -state disabled 1130 set waitMsg 1 1131} 1132 1133proc doWakeup {} { 1134 global ExecSh 1135 global ModDir 1136 1137 if $ExecSh { 1138 catch {exec sh -c $ModDir/ncid-wakeup} oops 1139 } else { 1140 catch {exec $ModDir/ncid-wakeup} oops 1141 } 1142} 1143 1144# PopupTime = 0: doPopup is disabled 1145# PopupTime = 1-5: Time in seconds window is forced to remain 1146# on top before user is allowed to remove it. 1147proc doPopup {} { 1148 global PopupTime 1149 1150 if {! $PopupTime} { return } 1151 1152 wm deiconify . 1153 raise . 1154 wm attributes . -topmost true 1155 after [expr $PopupTime*1000] wm attributes . -topmost false 1156} 1157 1158proc checkType {dataBlock} { 1159 1160 set rtn 0 1161 # Determine label type 1162 # General classifications: 1163 # 1 = real time: calls that can trigger WakeUp - CID, HUP, OUT, RID 1164 # 2 = real time: other calls - BLK, MWI, PID, PUT, WID 1165 # 3 = real time: ring detected - CIDINFO 1166 # 4 = real time: messages (non-calls) 1167 # 5 = log file : messages (non-calls) 1168 # 6 = log file : calls classified as 1 and 2 with suffix LOG 1169 # 7 = log file : unrecognized line type 1170 # 8 = real time: relay job - RLY 1171 # 9 = log file : relay job - RLYLOG 1172 # 10 = real time: call accounting - END 1173 # 11 = log file : call accounting - ENDLOG 1174 if [string match CID:* $dataBlock] {set rtn 1 1175 } elseif [string match HUP:* $dataBlock] {set rtn 1 1176 } elseif [string match OUT:* $dataBlock] {set rtn 1 1177 } elseif [string match RID:* $dataBlock] {set rtn 1 1178 1179 } elseif [string match BLK:* $dataBlock] {set rtn 2 1180 } elseif [string match MWI:* $dataBlock] {set rtn 2 1181 } elseif [string match PID:* $dataBlock] {set rtn 2 1182 } elseif [string match PUT:* $dataBlock] {set rtn 2 1183 } elseif [string match WID:* $dataBlock] {set rtn 2 1184 1185 } elseif [string match CIDINFO:* $dataBlock] {set rtn 3 1186 1187 } elseif [string match MSG:* $dataBlock] {set rtn 4 1188 } elseif [string match NOT:* $dataBlock] {set rtn 4 1189 1190 } elseif [string match MSGLOG:* $dataBlock] {set rtn 5 1191 } elseif [string match NOTLOG:* $dataBlock] {set rtn 5 1192 1193 } elseif [string match BLKLOG:* $dataBlock] {set rtn 6 1194 } elseif [string match CIDLOG:* $dataBlock] {set rtn 6 1195 } elseif [string match HUPLOG:* $dataBlock] {set rtn 6 1196 } elseif [string match MWILOG:* $dataBlock] {set rtn 6 1197 } elseif [string match OUTLOG:* $dataBlock] {set rtn 6 1198 } elseif [string match PIDLOG:* $dataBlock] {set rtn 6 1199 } elseif [string match PUTLOG:* $dataBlock] {set rtn 6 1200 } elseif [string match RIDLOG:* $dataBlock] {set rtn 6 1201 } elseif [string match WIDLOG:* $dataBlock] {set rtn 6 1202 1203 } elseif [string match LOG:* $dataBlock] {set rtn 7 1204 1205 } elseif [string match RLY:* $dataBlock] {set rtn 8 1206 1207 } elseif [string match RLYLOG:* $dataBlock] {set rtn 9 1208 1209 } elseif [string match END:* $dataBlock] {set rtn 10 1210 1211 } elseif [string match ENDLOG:* $dataBlock] {set rtn 11} 1212 logMsg $::LEVEL6 "Assigned $rtn for $dataBlock" 1213 return $rtn 1214} 1215 1216# must be sure the line passed checkType 1217# returns: $ciddate $cidtime $cidnumber $cidname $cidline $linetype "" "" 1218proc formatCID {dataBlock} { 1219 global lineID lineIDWidth 1220 1221 set cidname [formatNAME $dataBlock] 1222 set cidnumber [formatNMBR $dataBlock] 1223 set ciddate [formatDATE $dataBlock] 1224 set cidtime [formatTIME $dataBlock] 1225 set cidline "" 1226 if [string match {*\*LINE\**} $dataBlock] { 1227 set cidline [formatLINE $dataBlock] 1228 } 1229 # set default line indicator, should not be needed anymore 1230 if {$cidline == ""} { 1231 set cidline "-" 1232 for {set x 0} {$x < $lineIDWidth} {incr x} { 1233 set cidline "$cidline " 1234 } 1235 } 1236 # create call line label 1237 regsub { *$} $cidline {} lineID 1238 # set type of call 1239 if {![regsub {(\w+)LOG:.*} $dataBlock {\1} linetype]} { 1240 regsub {(\w+):.*} $dataBlock {\1} linetype 1241 } 1242 1243 return [list $ciddate $cidtime $cidnumber $cidname $cidline $linetype "" ""] 1244} 1245 1246# returns: $msgdate $msgtime $msgnumber $msgname $msgline $linetype $mesgtype $message 1247proc formatMSG {dataBlock} { 1248 1249 if {![regsub {(\w+)LOG:.*} $dataBlock {\1} linetype]} { 1250 regsub {(\w+):.*} $dataBlock {\1} linetype 1251 } 1252 1253 if {[regexp {\*\*\*DATE} $dataBlock]} { 1254 set msgdate [formatDATE $dataBlock] 1255 set msgtime [formatTIME $dataBlock] 1256 set msgname [formatNAME $dataBlock] 1257 set msgnmbr [formatNMBR $dataBlock] 1258 set msgline [formatLINE $dataBlock] 1259 set msgtype [formatMTYPE $dataBlock] 1260 regsub {\w+:\s+(.*) \*\*\*DATE.*} $dataBlock {\1\2} mesg 1261 set message [list $msgdate $msgtime $msgnmbr $msgname $msgline $linetype $msgtype $mesg] 1262 } else { 1263 regsub {\w+:\s+(.*)} $dataBlock {\1} mesg 1264 set message [list {} {} {} {} {} $linetype {} $mesg] 1265 } 1266 1267 return $message 1268} 1269 1270proc formatMTYPE {dataBlock} { 1271 if {[regexp {\*\*\*DATE.*MTYPE} $dataBlock]} { 1272 set msgtype [getField MTYPE $dataBlock] 1273 } else { 1274 set msgtype "-" 1275 } 1276 return $msgtype 1277} 1278 1279proc formatLINE {dataBlock} { 1280 set cidline [getField LINE $dataBlock] 1281 return $cidline 1282} 1283 1284proc formatDATE {dataBlock} { 1285 global AltDate DateSepar YearDot 1286 1287 set ciddate [getField DATE $dataBlock] 1288 # slash (/) is the default date separator 1289 if {$AltDate} { 1290 # Date format: DDMMYY or DDMM 1291 if {![regsub {([0-9][0-9])([0-9][0-9])([0-9][0-9][0-9][0-9])} \ 1292 $ciddate {\2/\1/\3} ciddate]} { 1293 regsub {([0-9][0-9])([0-9][0-9].*)} $ciddate {\2/\1} ciddate 1294 } 1295 } else { 1296 # Date format: MMDDYY or MMDD 1297 if {![regsub {([0-9][0-9])([0-9][0-9])([0-9][0-9][0-9][0-9])} \ 1298 $ciddate {\1/\2/\3} ciddate]} { 1299 regsub {([0-9][0-9])([0-9][0-9].*)} $ciddate {\1/\2} ciddate 1300 } 1301 } 1302 if {$DateSepar == "-"} { 1303 # set hyphen (-) as date separator 1304 regsub -all {/} $ciddate - ciddate 1305 } elseif {$DateSepar == "."} { 1306 if $YearDot { 1307 # set period (.) as date separator and append it to year (ordinal numbers) 1308 regsub -all {/} $ciddate. . ciddate 1309 } else { 1310 # set period (.) as date separator 1311 regsub -all {/} $ciddate . ciddate 1312 } 1313 } 1314 return $ciddate 1315} 1316 1317proc formatTIME {dataBlock} { 1318 global clock 1319 1320 set cidtime [getField TIME $dataBlock] 1321 if ([regexp {(\d{2})(\d{2})} $cidtime time hours minutes]) { 1322 if {$clock == 24} { 1323 set cidtime "$hours:$minutes" 1324 } else { 1325 set cidtime [convertTo12 $hours $minutes] 1326 } 1327 } 1328 return $cidtime 1329} 1330 1331proc formatNAME {dataBlock} { 1332 set cidname [getField NAME $dataBlock] 1333 if {$cidname == "-"} {set cidname "NO NAME"} 1334 return $cidname 1335} 1336 1337proc checkCountry {code} { 1338 global countryCodes NoGUI 1339 1340 if {![regexp "$code" $countryCodes]} { 1341 if {!$NoGUI} { 1342 logMsg $::LEVEL1 "Country Code \"$code\" is not supported.\nShould be one of \"$countryCodes\"." 1343 } 1344 exitMsg 7 "Country Code \"$code\" is not supported.\nShould be one of \"$countryCodes\"." 1345 } 1346} 1347 1348proc formatNMBR {dataBlock} { 1349 global Country NoOne 1350 # https://en.wikipedia.org/wiki/National_conventions_for_writing_telephone_numbers 1351 1352 set cidnumber [getField NMBR $dataBlock] 1353 if {$cidnumber == "-"} {set cidnumber "NO-NUMBER"} 1354 switch $Country { 1355 DE {set cidnumber [formatDE $cidnumber]} 1356 FR {set cidnumber [formatFR $cidnumber]} 1357 HR {set cidnumber [formatHR $cidnumber]} 1358 SE {set cidnumber [formatSE $cidnumber]} 1359 UK {set cidnumber [formatUK $cidnumber]} 1360 US {set cidnumber [formatUS $cidnumber]} 1361 NONE {} 1362 DEFAULT { 1363 exitMsg 7 "Country Code \"$Country\" is not supported. Please change it." 1364 } 1365 } 1366 return $cidnumber 1367} 1368 1369proc formatUS {cidnumber} { 1370 global NoOne 1371 # https://en.wikipedia.org/wiki/North_American_Numbering_Plan 1372 # US-PBX examples: 919715559679 -> 9,1-971-555-9679 1373 # 99715559679 -> 9,971-555-9679 1374 if {![regsub {(9)(1)([0-9]{3})([0-9]{3})([0-9]{4})} \ 1375 $cidnumber {\1,\2-\3-\4-\5} cidnumber]} { 1376 if {![regsub {(9)([0-9]{3})([0-9]{3})([0-9]{4})} \ 1377 $cidnumber {\1,\2-\3-\4} cidnumber]} { 1378 if {![regsub {(1)([0-9]{3})([0-9]{3})([0-9]{4})} \ 1379 $cidnumber {\1-\2-\3-\4} cidnumber]} { 1380 if {![regsub {(ob)([0-9]{3})([0-9]{3})([0-9]{3})} \ 1381 $cidnumber {\1-\2-\3-\4} cidnumber]} { 1382 if {![regsub {^([0-9]{3})([0-9]{3})([0-9]{3})$} \ 1383 $cidnumber {\1-\2-\3} cidnumber]} { 1384 if {![regsub {([0-9]{3})([0-9]{3})([0-9]{4})} \ 1385 $cidnumber {\1-\2-\3} cidnumber]} { 1386 regsub {([0-9]{3})([0-9]{4})} \ 1387 $cidnumber {\1-\2} cidnumber 1388 } 1389 } 1390 } 1391 } 1392 } 1393 } elseif {$NoOne} { 1394 regsub {^1-?(.*)} $cidnumber {\1} cidnumber 1395 } 1396 return $cidnumber 1397} 1398 1399proc formatUK {cidnumber} { 1400 # https://en.wikipedia.org/wiki/United_Kingdom_area_codes 1401 if {![regsub {^(011[0-9])([0-9]{3})([0-9]+)} \ 1402 $cidnumber {\1-\2-\3} cidnumber]} { 1403 if {![regsub {^(01[0-9]1)([0-9]{3})([0-9]+)} \ 1404 $cidnumber {\1-\2-\3} cidnumber]} { 1405 if {![regsub {^(13873|15242|19467)([0-9]{4,5})} \ 1406 $cidnumber {\1-\2} cidnumber]} { 1407 if {![regsub {^(153)(94|95|96)([0-9]{4,5})} \ 1408 $cidnumber {\1\2-\3} cidnumber]} { 1409 if {![regsub {^(169)(73|74|77)([0-9]{4,5})} \ 1410 $cidnumber {\1\2-\3} cidnumber]} { 1411 if {![regsub {^(176)(83|84|87)([0-9]{4,5})} \ 1412 $cidnumber {\1\2-\3} cidnumber]} { 1413 if {![regsub {^(01[0-9]{3})([0-9]+)} \ 1414 $cidnumber {\1-\2} cidnumber]} { 1415 if {![regsub {^(02[0-9])([0-9]{4})([0-9]+)} \ 1416 $cidnumber {\1-\2-\3} cidnumber]} { 1417 if {![regsub {^(0[389][0-9]{2})([0-9]{3})([0-9]+)} \ 1418 $cidnumber {\1-\2-\3} cidnumber]} { 1419 if {![regsub {^(07[0-9]{3})([0-9]+)} \ 1420 $cidnumber {\1-\2} cidnumber]} { 1421 } 1422 } 1423 } 1424 } 1425 } 1426 } 1427 } 1428 } 1429 } 1430 } 1431 return $cidnumber 1432} 1433 1434proc formatSE {cidnumber} { 1435 # https://en.wikipedia.org/wiki/Telephone_numbers_in_Sweden#Area_codes 1436 if {![regsub {^(07[0-9])([0-9]+)} \ 1437 $cidnumber {\1-\2} cidnumber]} { 1438 if {![regsub {^(08)([0-9]+)} \ 1439 $cidnumber {\1-\2} cidnumber]} { 1440 if {![regsub {^(01[013689])([0-9]+)} \ 1441 $cidnumber {\1-\2} cidnumber]} { 1442 if {![regsub {^(0[23][[136])([0-9]+)} \ 1443 $cidnumber {\1-\2} cidnumber]} { 1444 if {![regsub {^(04[0246])([0-9]+)} \ 1445 $cidnumber {\1-\2} cidnumber]} { 1446 if {![regsub {^(054)([0-9]+)} \ 1447 $cidnumber {\1-\2} cidnumber]} { 1448 if {![regsub {^(06[02])([0-9]+)} \ 1449 $cidnumber {\1-\2} cidnumber]} { 1450 if {![regsub {^(090)([0-9]+)} \ 1451 $cidnumber {\1-\2} cidnumber]} { 1452 regsub {^([0-9]{4})([0-9]+)} \ 1453 $cidnumber {\1-\2} cidnumber 1454 } 1455 } 1456 } 1457 } 1458 } 1459 } 1460 } 1461 } 1462 return $cidnumber 1463} 1464 1465proc formatDE {cidnumber} { 1466 # https://en.wikipedia.org/wiki/Area_codes_in_Germany 1467 1468 # format for numbers was broken, removed until it can be done correctly 1469 return $cidnumber 1470} 1471 1472proc formatHR {cidnumber} { 1473 # https://en.wikipedia.org/wiki/Telephone_numbers_in_Croatia 1474 if {![regsub {^(01)([0-9]+)} \ 1475 $cidnumber {\1-\2} cidnumber]} { 1476 if {![regsub {^(02[0123])([0-9]+)} \ 1477 $cidnumber {\1-\2} cidnumber]} { 1478 if {![regsub {^(03[12345])([0-9]+)} \ 1479 $cidnumber {\1-\2} cidnumber]} { 1480 if {![regsub {^(04[0234789])([0-9]+)} \ 1481 $cidnumber {\1-\2} cidnumber]} { 1482 if {![regsub {^(05[123])([0-9]+)} \ 1483 $cidnumber {\1-\2} cidnumber]} { 1484 if {![regsub {^(09[125789])([0-9]+)} \ 1485 $cidnumber {\1-\2} cidnumber]} { 1486 } 1487 } 1488 } 1489 } 1490 } 1491 } 1492 return $cidnumber 1493} 1494 1495proc formatFR {cidnumber} { 1496 # http://en.wikipedia.org/wiki/Telephone_numbers_in_France 1497 set nmbrWidth 20 1498 #French national calls 1499 if {![regsub {^(0[1-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])} \ 1500 $cidnumber {\1 \2 \3 \4 \5} cidnumber]} { 1501 #international calls (prefix 1* ,2 ) 1502 #formats prefix but doesn't format local number 1503 if {![regsub {^(00)(1)([1-9]+)} \ 1504 $cidnumber {(+1) \3 } cidnumber]} { 1505 } 1506 if {![regsub {^(00)(2[078])([0-9]+)} \ 1507 $cidnumber {(+\2) \3 } cidnumber]} { 1508 } 1509 if {![regsub {^(00)(2[1234569][0-9])([0-9]+)} \ 1510 $cidnumber {(+\2) \3 } cidnumber]} { 1511 } 1512 if {![regsub {^(00)(3[012469])([0-9]+)} \ 1513 $cidnumber {(+\2) \3 } cidnumber]} { 1514 } 1515 if {![regsub {^(00)(3[578][0-9])([0-9]+)} \ 1516 $cidnumber {(+\2) \3 } cidnumber]} { 1517 } 1518 #telemarketing calls with France international prefix 1519 #formats prefix and formats local number to french standard 1520 if {![regsub {^(00)(33)([1-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9]+)} \ 1521 $cidnumber {(+33) \3 \4 \5 \6 \7} cidnumber]} { 1522 } 1523 #other international calls (prefix 3*,4*,5*,6*,7*,8*,9*) 1524 #formats prefix but doesn't format local number 1525 if {![regsub {^(00)(4[013456789])([0-9]+)} \ 1526 $cidnumber {(+\2) \3 } cidnumber]} { 1527 } 1528 if {![regsub {^(00)(4[2][0-9])([0-9]+)} \ 1529 $cidnumber {(+\2) \3 } cidnumber]} { 1530 } 1531 if {![regsub {^(00)(5[1345678])([0-9]+)} \ 1532 $cidnumber {(+\2) \3 } cidnumber]} { 1533 } 1534 if {![regsub {^(00)(5[09][0-9])([0-9]+)} \ 1535 $cidnumber {(+\2) \3 } cidnumber]} { 1536 } 1537 if {![regsub {^(00)(6[013456])([0-9]+)} \ 1538 $cidnumber {(+\2) \3 } cidnumber]} { 1539 } 1540 if {![regsub {^(00)(6[789][0-9])([0-9]+)} \ 1541 $cidnumber {(+\2) \3 } cidnumber]} { 1542 } 1543 if {![regsub {^(00)(7)([1-9]+)} \ 1544 $cidnumber {(+7) \3 } cidnumber]} { 1545 } 1546 if {![regsub {^(00)(8[123469])([0-9]+)} \ 1547 $cidnumber {(+\2) \3 } cidnumber]} { 1548 } 1549 if {![regsub {^(00)(8[0578][0-9])([0-9]+)} \ 1550 $cidnumber {(+\2) \3 } cidnumber]} { 1551 } 1552 if {![regsub {^(00)(9[0123458])([0-9]+)} \ 1553 $cidnumber {(+\2) \3 } cidnumber]} { 1554 } 1555 if {![regsub {^(00)(9[679][0-9])([0-9]+)} \ 1556 $cidnumber {(+\2) \3 } cidnumber]} { 1557 } 1558 } 1559 return $cidnumber 1560} 1561 1562proc convertTo12 {hours minutes} { 1563 set AmPm "am" 1564 if {$hours > 12} { 1565 set hours [expr $hours - 12] 1566 set AmPm "pm" 1567 } elseif {$hours == 12} { 1568 set AmPm "pm" 1569 } elseif {$hours == 0} { 1570 set hours 12 1571 } 1572 regsub {^(0|\s|)?(\d)$} $hours { \2} hours 1573 return "$hours:$minutes $AmPm" 1574} 1575 1576proc convertTo24 {hours minutes AmPm} { 1577 if {$hours == 12 && $AmPm eq "am"} { 1578 set hours 0 1579 } elseif {$hours != 12 && $AmPm eq "pm"} { 1580 set hours [expr $hours + 12] 1581 } 1582 regsub {^(0|\s|)?(\d)$} $hours {0\2} hours 1583 return "$hours:$minutes" 1584} 1585 1586# extract field pair where 'dataString' is the field label (NAME, NMBR, etc.) 1587# and $result is the field data 1588proc getField {dataString dataBlock} { 1589 regsub ".*\\*$dataString\\*" $dataBlock {} result 1590 1591 switch $dataString { 1592 RING - 1593 DATE - 1594 TIME { 1595 regsub {(\d+).*} $result {\1} result 1596 } 1597 LINE { 1598 regsub {([\w\s@!-]+)\*.*} $result {\1} result 1599 } 1600 NMBR - 1601 NAME { 1602 regsub {\*DATE\*.*|\*TIME\*.*$|\*LINE\*.*|\*NMBR\*.*|\*MESG\*.*|\*NAME\*.*|\*MTYPE\*.*|\*$} $result "" result 1603 } 1604 MTYPE - 1605 default { 1606 regsub {([\w-]+)\*} $result {\1} result 1607 } 1608 } 1609 return $result 1610} 1611 1612# send the CID information to an external program 1613# Input: $ciddate $cidtime $cidnumber $cidname $cidline $cidtype "" "" 1614proc sendCID {cid} { 1615 global Module ExecSh ModDir WakeUp 1616 1617 set modcid "$cid" 1618 # send DATE\nTIME\nNUMBER\nNAME\nLINE\nTYPE\nMESG\nMTYPE\n 1619 set modtype "using a module" 1620 set modin "[lindex $cid 0]\n[lindex $cid 1]\n[lindex $cid 2]\n[lindex $cid 3]\n[lindex $cid 4]\n[lindex $cid 5]\n[lindex $cid 6]\n[lindex $cid 7]" 1621 if $ExecSh { 1622 catch {exec sh -c $Module << "$modin" >@stdout &} oops 1623 } else { 1624 catch {exec $Module << "$modin" >@stdout &} oops 1625 } 1626 logMsg $::LEVEL1 "$modtype\nSent $Module $modcid" 1627} 1628 1629# pass the message to an external program 1630# input: $msgdate $msgtime $msgnumber $msgname $msgline $msgtype $mtype $msg 1631proc sendMSG {msg} { 1632 global Module ExecSh preClient_1_0 1633 1634 set mesg "$msg" 1635 if $preClient_1_0 { 1636 # send "\n\n\nMESG\n\nTYPE\n" 1637 set modtype "using a preClient 1.0 module for a message" 1638 set modin "[lindex $msg 0]\n[lindex $msg 1]\n[lindex $msg 2]\n[lindex $msg 6]\n[lindex $msg 4]\n[lindex $msg 5]\n[lindex $msg 3]\n" 1639 set mesg [lreplace $mesg 3 3 [lindex $msg 7]] 1640 set mesg [lreplace $mesg 7 7 [lindex $msg 3]] 1641 if $ExecSh { 1642 catch {exec sh -c $Module << "$modin" >@stdout &} oops 1643 } else { 1644 catch {exec $Module << "$modin" >@stdout &} oops 1645 } 1646 } else { 1647 # send "DATE\nTIME\nNMBR\nNAME\nLINE\nTYPE\n\MESG\nMTYPE\n" 1648 set modtype "using a Client 1.0 type module for a message" 1649 set modin "[lindex $msg 0]\n[lindex $msg 1]\n[lindex $msg 2]\n[lindex $msg 3]\n[lindex $msg 4]\n[lindex $msg 5]\n[lindex $msg 7]\n[lindex $msg 6]\n" 1650 set mesg "[list [lindex $msg 0]\n[lindex $msg 1]\n[lindex $msg 2]\n[lindex $msg 3]\n[lindex $msg 4]\n[lindex $msg 5]\n[lindex $msg 7]\n[lindex $msg 6]]\n" 1651 if $ExecSh { 1652 catch {exec sh -c $Module << "$modin" >@stdout &} oops 1653 } else { 1654 catch {exec $Module << "$modin" >@stdout &} oops 1655 } 1656 } 1657 logMsg $::LEVEL1 "$modtype\nSent $Module $mesg" 1658} 1659 1660# display CID information or message 1661# Input: $ciddate $cidtime $cidnumber $cidname $cidline $type "" "" 1662# $msgdate $msgtime $msgnumber $msgname $msgline $type message msgio 1663# ismsg = 0 for CID and 1 for message 1664proc displayCID {input ismsg} { 1665 global Txt historyTextWidth 1666 1667 if {$ismsg} { 1668 set maxwidth [expr $historyTextWidth - 30] 1669 set firstNewline [string first "\n" $input] 1670 if {($firstNewline == [expr [string length $input] - 1]) && ([string length $input] > $maxwidth)} { 1671 logMsg $::LEVEL2 "Truncating long message of length [string length $input] to fit within width $maxwidth" 1672 set Txt "[string range [string trim $input] 0 $maxwidth](truncated)" 1673 } else { 1674 # string is not too long OR string has embedded new lines already 1675 set Txt $input 1676 } 1677 } else { 1678 set Txt "[lindex $input 3]\n[lindex $input 2]" 1679 } 1680} 1681 1682# display Call Log 1683# Input: $ciddate $cidtime $cidnumber $cidname $cidline $linetype "" "" 1684# Input: $msgdate $msgtime $msgnumber $msgname $msgline $linetype $msgtype message 1685proc displayLog {input ismsg} { 1686 global Module NoGUI 1687 global display_line_num DoingCallLog 1688 global nmbrWidth nameWidth lineIDWidth mtypeWidth 1689 global hup label 1690 global hupColor ltColor dateColor timeColor lineColor nmbrColor nameColor 1691 1692 if $NoGUI { 1693 if {$Module == ""} { 1694 if $ismsg { 1695 if {[lindex $input 1] eq {}} { 1696 logMsg $::LEVEL1 "[lindex $input 6]: [lindex $input 7]" 1697 } else { 1698 logMsg $::LEVEL1 "[lindex $input 5]: [lindex $input 0] [lindex $input 1] [lindex $input 4] [lindex $input 2] [lindex $input 3] [lindex $input 6] [lindex $input 7]" 1699 } 1700 } else { 1701 logMsg $::LEVEL1 "[lindex $input 5]: [lindex $input 0] [lindex $input 1] [lindex $input 4] [lindex $input 2] [lindex $input 3]" 1702 } 1703 } 1704 incr display_line_num 1705 } else { 1706 # GUI 1707 incr display_line_num 1708 if {! $DoingCallLog} {.vh configure -state normal} 1709 if {[lindex $input 1] eq {}} { 1710 .vh insert end "\n[lindex $input 5]: " lttag [lindex $input 7] msgtag 1711 } else { 1712 set ciddate [lindex $input 0] 1713 set cidtime [lindex $input 1] 1714 set cidnmbr [format "%${nmbrWidth}.${nmbrWidth}s" [lindex $input 2]] 1715 set cidname [format "%-${nameWidth}.${nameWidth}s" [lindex $input 3]] 1716 set cidline [format "%-${lineIDWidth}.${lineIDWidth}s" \ 1717 [lindex $input 4]] 1718 set linetype [lindex $input 5] 1719 1720 if {$label != 6 && $linetype == "HUP"} { 1721 1722 # hup array used to restore normal color to $linetype 1723 set lineid [string trimright $cidline] 1724 array set hup "{$lineid} $display_line_num" 1725 1726 # set HUP active color to $linetype 1727 .vh insert end "\n$linetype: " huptag 1728 } else { 1729 # set theme color to $linetype 1730 .vh insert end "\n$linetype: " lttag 1731 } 1732 1733 .vh insert end "$ciddate " datetag \ 1734 "$cidtime " timetag \ 1735 "$cidline " linetag \ 1736 "$cidnmbr " nmbrtag \ 1737 "$cidname " nametag 1738 1739 if $ismsg { 1740 set msgtype [format "%-${mtypeWidth}.${mtypeWidth}s" \ 1741 [lindex $input 6]] 1742 set message [lindex $input 7] 1743 .vh insert end "$msgtype " mttag $message msgtag 1744 } 1745 } 1746 if {! $DoingCallLog} { 1747 if {$display_line_num == 1} { 1748 .vh delete 1.0 2.0 1749 } 1750 .vh yview moveto 1.0 1751 .vh configure -state disabled 1752 if {[lindex [.vh yview] 0] + [lindex [.vh yview] 1] == 1.0} { 1753 grid .ys 1754 } 1755 } 1756 } 1757} 1758 1759#https://www.rosettacode.org/wiki/Word_wrap#Tcl 1760#label widgets don't have a -wrap option so use this 1761proc wrapParagraph {width text} { 1762 regsub -all {\s+} [string trim $text] " " text 1763 set RE "^(.{1,$width})(?:\\s+(.*))?$" 1764 for {set result ""} {[regexp $RE $text -> line text]} {} { 1765 append result $line "\n" 1766 } 1767 return [string trimright $result "\n"] 1768} 1769 1770# Open a connection to the NCID server 1771proc connectCID {} { 1772 global Host Port 1773 global Try Delay 1774 global Socket menuDisabled 1775 global NoGUI 1776 global VersionInfo VersionIDENT HostnameFlag hostname 1777 global Module dtfile 1778 global CallLog 1779 1780 set ServerOptions "" 1781 set Socket 0 1782 1783 if {!$NoGUI} { 1784 if {$::tcl_platform(platform) == "unix"} { 1785 set menu .menubar.file 1786 1787 # enable or disable autostart menu 1788 if ![file isfile $dtfile] { 1789 $menu entryconfigure Auto*Start -state disabled 1790 } else { 1791 $menu entryconfigure Auto*Start -state normal 1792 } 1793 } 1794 set menu .menubar.server 1795 } 1796 1797 logServerAddress 1798 logMsg $::LEVEL3 "Attempting to connect" 1799 1800 while (1) { 1801 # open socket to server 1802 if {[catch {set Socket [socket $Host $Port]} msg]} { 1803 if {!$NoGUI} { 1804 if {$menuDisabled == 0} { 1805 $menu entryconfigure Reload* -state disabled 1806 $menu entryconfigure Update*current* -state disabled 1807 $menu entryconfigure Update*all*call* -state disabled 1808 $menu entryconfigure Reread* -state disabled 1809 $menu entryconfigure Dial*Number* -state disabled 1810 set menuDisabled 1 1811 1812 # a delay of 1 second causes Reconnect to break ncid 1813 if {$Delay == 1} { 1814 .menubar.file entryconfigure Reconnect* -state disabled 1815 } 1816 } 1817 } 1818 set Try [expr $Try + 1] 1819 tryCount "$Host:$Port - $msg\n" 1820 } else { 1821 # set socket to non-blocking 1822 fconfigure $Socket -blocking 0 1823 # get response from server as an event 1824 fileevent $Socket readable getCID 1825 1826 if {!$NoGUI && $menuDisabled} { 1827 $menu entryconfigure Reload* -state normal 1828 $menu entryconfigure Update*current* -state normal 1829 $menu entryconfigure Update*all*call* -state normal 1830 $menu entryconfigure Reread* -state normal 1831 set menuDisabled 0 1832 1833 if {$Delay == 1} { 1834 .menubar.file entryconfigure Reconnect* -state normal 1835 } 1836 } 1837 1838 puts $Socket "HELLO: IDENT: $VersionIDENT" 1839 flush $Socket 1840 logMsg $::LEVEL1 "HELLO: IDENT: $VersionIDENT" 1841 if $NoGUI { 1842 logMsg $::LEVEL1 "Connected to $Host:$Port" 1843 if $CallLog { 1844 # tell server to send call log 1845 puts $Socket "HELLO: CMD: log" 1846 flush $Socket 1847 logMsg $::LEVEL1 "Sent: HELLO: CMD: log" 1848 } else { 1849 # tell server to not send call log 1850 puts $Socket "HELLO: CMD: no_log" 1851 flush $Socket 1852 logMsg $::LEVEL1 "Sent: HELLO: CMD: no_log" 1853 } 1854 } else { 1855 clearLog 1856 displayCID "Connected to\n$Host:$Port" 1 1857 logMsg $::LEVEL1 "Connected to $Host:$Port" 1858 } 1859 break 1860 } 1861 } 1862} 1863 1864# valid option with argument examples: -v 1 | -v1 | --verbose 1 | --verbose=1 1865# combined options are not handled, for example: -AcHXW 1866proc handleOptArg {} { 1867 global Usage Opt OptArg OptCnt 1868 1869 set gotarg 0 1870 if {[regexp {^--} $Opt]} { 1871 set len [string length $Opt] 1872 set pos [string first = $Opt] 1873 if {$pos != -1 && $len > $pos} { 1874 set OptArg [string range $Opt [expr $pos + 1] $len] 1875 set Opt [string range $Opt 0 [expr $pos - 1]] 1876 } else {incr OptCnt} 1877 } else { 1878 if {[string length $Opt] > 2} { 1879 # single letter option combined with argument 1880 set OptArg [string range $Opt 2 [string length $Opt]] 1881 set Opt [string range $Opt 0 1] 1882 } else {incr OptCnt} 1883 } 1884 1885 if {$OptArg == ""} {exitMsg 6 "Missing $Opt argument\n$Usage\n"} 1886} 1887 1888proc getArg {} { 1889 # note: debug log has not been opened yet so logMsg is unavailable 1890 global Opt OptArg OptCnt OptPmsg delayedMsgs 1891 global Host Port Hosts HostIndex oldHost oldPort SelectedLineIDs 1892 global Delay 1893 global Usage 1894 global NoGUI 1895 global Verbose 1896 global LogEnable LogDir 1897 global Module ModDir Ring CallOnRing 1898 global HostnameFlag 1899 global PIDfile 1900 global PopupTime 1901 global NoExit 1902 global AltDate 1903 global WakeUp 1904 global Version 1905 global WrapLines 1906 global CallLog 1907 global NightMode Country 1908 1909 set showUsage 0 1910 set hostport 0 1911 1912 for {set OptCnt 0} {$OptCnt < $::argc} {incr OptCnt} { 1913 set OptArg [lindex $::argv [expr $OptCnt + 1]] 1914 switch -regexp -- [set Opt [lindex $::argv $OptCnt]] { 1915 {^-r} - 1916 {^--ring$|^--ring=} { 1917 handleOptArg 1918 if {[regexp {^-[129]$} $OptArg] 1919 || [regexp {^[0123456789]$} $OptArg]} { 1920 set Ring $OptArg 1921 set CallOnRing 1 1922 } else {exitMsg 4 "Invalid $Opt argument: $OptArg\n$Usage\n"} 1923 } 1924 {^--no-gui$} {set NoGUI 1} 1925 {^--night-mode$} {set NightMode 1} 1926 {^-A$} - 1927 {^--alt-date$} {set AltDate 1} 1928 {^-c$} - 1929 {^--call-log$} {set CallLog 1} 1930 {^-C} - 1931 {^--country-code$|^--country-code=} { 1932 handleOptArg 1933 checkCountry $OptArg 1934 set Country $OptArg 1935 } 1936 {^-D} - 1937 {^--delay$|^--delay=} { 1938 handleOptArg 1939 if {[regexp {^[0-9]+$} $OptArg]} { 1940 set Delay $OptArg 1941 } else {exitMsg 4 "Invalid $Opt argument: $OptArg\n$Usage\n"} 1942 } 1943 {^-h$} - 1944 {^--help$} {set showUsage 1; set NoGUI 1} 1945 {^-H$} - 1946 {^--hostname-flag$} {set HostnameFlag 1} 1947 {^-l} - 1948 {^--log-enable$|^--log-enable=} { 1949 handleOptArg 1950 if {[regexp {^[0-2]+$} $OptArg]} { 1951 set LogEnable $OptArg 1952 } else {exitMsg 4 "Invalid $Opt argument: $OptArg\n$Usage\n"} 1953 } 1954 {^-L} - 1955 {^--log-dir$|^--log-dir=} { 1956 handleOptArg 1957 if {$OptArg == ""} { 1958 exitMsg 4 "Invalid $Opt argument: $OptArg\n$Usage\n"} 1959 set LogDir $OptArg 1960 } 1961 {^-m} - 1962 {^--module$|^--module=} - 1963 {^-P$} - 1964 {^--program$} { 1965 if {$Opt == "-P" || $Opt == "--program"} { 1966 set delayedMsgs \ 1967 "$delayedMsgs\n***** WARNING: option -P|--program is deprecated, use option -m|--module" 1968 } 1969 handleOptArg 1970 if {[regexp {^.*/} $OptArg]} { 1971 set Module [list $OptArg] 1972 } else {set Module [list $ModDir/$OptArg]} 1973 } 1974 {^-p} - 1975 {^--pidfile$|^--pidfile=} { 1976 handleOptArg 1977 if {[regexp {^[\w./]+} $OptArg]} { 1978 set PIDfile $OptArg 1979 } else {exitMsg 4 "Invalid $Opt argument: $OptArg\n$Usage\n"} 1980 } 1981 {^-t} - 1982 {^--PopupTime$^--PopupTime=} { 1983 handleOptArg 1984 if {[regexp {^[0-5]$} $OptArg]} { 1985 set PopupTime $OptArg 1986 } else {exitMsg 4 "Invalid $Opt argument: $OptArg\n$Usage\n"} 1987 } 1988 {^-v} - 1989 {^--verbose$|--verbose=} { 1990 handleOptArg 1991 if {[regexp {^[1-9]+$} $OptArg]} { 1992 set Verbose $OptArg 1993 } else {exitMsg 4 "Invalid $Opt argument: $OptArg\n$Usage\n"} 1994 } 1995 {^-V$} - 1996 {^--version$} {set NoGUI 1; puts "ncid (NCID) $Version"; exit 0} 1997 {^-X$} - 1998 {^--noexit} {set NoExit 1} 1999 {^-W$} - 2000 {^--wakeup$} {set WakeUp 1} 2001 {^-.*$} {set NoGUI 1; exitMsg 5 "Unknown option: $Opt\n$Usage\n"} 2002 {^\d+$} {set Port $Opt; set hostport 1} 2003 {^.+$} {set Host $Opt; set hostport 1} 2004 default {set NoGUI 1; exitMsg 5 "Unknown option: $Opt\n$Usage\n"} 2005 } 2006 } 2007 2008 if {$showUsage} {exitMsg 1 "$Usage\n"} 2009 2010 if {$hostport} { 2011 set SelectedLineIDs "" 2012 if {[regexp {:} $Host]} { 2013 set Hosts $Host 2014 lassign [split $Hosts ":"] Host Port 2015 } else { 2016 set Hosts "$Host:$Port" 2017 } 2018 set delayedMsgs \ 2019 "$delayedMsgs\nncidd address temporarily changed to $Host:$Port" 2020 } 2021 set oldHost "" 2022 set oldPort "" 2023} 2024 2025# ttk Widgets: http://wiki.tcl-lang.org/14796 2026# https://tkdocs.com/tutorial/styles.html 2027# Styles and themes: http://www.tkdocs.com/tutorial/styles.html#using 2028# Changing ttk Widget Colors: https://wiki.tcl.tk/37973 2029# A collection of all the information on setting the 2030# colors of modern widgets in one place. 2031# 2032# sets styles for Day, Night, and themes (if needed) 2033proc setStyles {} { 2034 global ThemeName fgColor bckColor mtColor bckSelColor fgSelColor 2035 global hupColor dateColor timeColor lineColor nmbrColor nameColor 2036 global tvFgColor tvBckColor \ 2037 global vhFgColor vhBckColor vhInsColor 2038 2039 set enabletheme 0 2040 set m .menubar 2041 set items "file file.auto file.startup server server.hosts server.dial \ 2042 server.copy view view.types view.lines prefs theme help" 2043 2044 switch $ThemeName { 2045 night { 2046 set fgColor "yellow" 2047 set fg2Color "white" 2048 set fg3Color "cyan" 2049 set fgActColor "white" 2050 set fgSelColor "red" 2051 set bckColor "#262626" 2052 set bckActColor "#215d9c" 2053 set bckSelColor "#262626" 2054 set bck2SelColor "blue" 2055 set bckFldColor "#0f0f00" 2056 set bckFldActColor "#215d9c" 2057 set roColor "#0f0f00" 2058 set arrowColor "white" 2059 set arrowActColor "black" 2060 set indColor "black" 2061 set indSelColor "white" 2062 set indPressColor "white" 2063 set truColor "#3c3c3c" 2064 set selColor "white" 2065 set insColor "white" 2066 2067 # text colors 2068 set tvFgColor "yellow" 2069 set tvBckColor "#262626" 2070 set vhFgColor "white" 2071 set vhBckColor "#262626" 2072 set vhInsColor "white" 2073 2074 # history window column colors 2075 .vh tag configure huptag -foreground white -selectbackground blue 2076 .vh tag configure lttag -foreground #7fff7f -selectbackground blue 2077 .vh tag configure datetag -foreground yellow -selectbackground blue 2078 .vh tag configure timetag -foreground cyan -selectbackground blue 2079 .vh tag configure linetag -foreground #7fff7f -selectbackground blue 2080 .vh tag configure nmbrtag -foreground yellow -selectbackground blue 2081 .vh tag configure nametag -foreground cyan -selectbackground blue 2082 .vh tag configure mttag -foreground yellow -selectbackground blue 2083 .vh tag configure msgtag -foreground white -selectbackground blue 2084 } 2085 day { 2086 set fgColor "blue" 2087 set fg2Color "black" 2088 set fg3Color "green" 2089 set fgActColor "white" 2090 set fgSelColor "red" 2091 set bckColor "#d9d9d9" 2092 set bckActColor "#4a90d9" 2093 set bckSelColor "#d9d9d9" 2094 set bck2SelColor "blue" 2095 set bckFldColor "#f0f0ff" 2096 set bckFldActColor "#4a90d9" 2097 set roColor "#f0f0ff" 2098 set arrowColor "black" 2099 set arrowActColor "white" 2100 set indColor "#d9d9d9" 2101 set indSelColor "black" 2102 set indPressColor "black" 2103 set truColor "#c9c9c9" 2104 set selColor "black" 2105 set insColor "black" 2106 2107 #text colors 2108 set tvBckColor "white" 2109 set tvFgColor "blue" 2110 set vhBckColor "white" 2111 set vhFgColor "black" 2112 set vhInsColor "white" 2113 2114 # history window column colors 2115 .vh tag configure huptag -foreground black -selectbackground lightgreen 2116 .vh tag configure lttag -foreground purple -selectbackground lightgreen 2117 .vh tag configure datetag -foreground blue -selectbackground lightgreen 2118 .vh tag configure timetag -foreground red -selectbackground lightgreen 2119 .vh tag configure linetag -foreground purple -selectbackground lightgreen 2120 .vh tag configure nmbrtag -foreground blue -selectbackground lightgreen 2121 .vh tag configure nametag -foreground red -selectbackground lightgreen 2122 .vh tag configure mttag -foreground blue -selectbackground lightgreen 2123 .vh tag configure msgtag -foreground black -selectbackground lightgreen 2124 } 2125 default { 2126 set enabletheme 1 2127 2128 set fgColor "black" 2129 set fg2Color "black" 2130 set fg3Color "black" 2131 set fgActColor "black" 2132 set fgSelColor "black" 2133 set bckColor "#d9d9d9" 2134 set bckActColor "#d9d9d9" 2135 set bckSelColor "#d9d9d9" 2136 set bck2SelColor "blue" 2137 set bckFldColor "#f0f0ff" 2138 set bckFldActColor "#d9d9d9" 2139 set roColor "#f0f0ff" 2140 set arrowColor "black" 2141 set arrowActColor "black" 2142 set indColor "#d9d9d9" 2143 set indSelColor "black" 2144 set indPressColor "black" 2145 set truColor "#c9c9c9" 2146 set selColor "black" 2147 set insColor "black" 2148 2149 #text colors 2150 set tvBckColor "white" 2151 set tvFgColor "black" 2152 set vhBckColor "white" 2153 set vhFgColor "black" 2154 set vhInsColor "white" 2155 2156 # history window column colors 2157 .vh tag configure huptag -foreground black -selectbackground #d9d9d9 2158 .vh tag configure lttag -foreground black -selectbackground #d9d9d9 2159 .vh tag configure datetag -foreground black -selectbackground #d9d9d9 2160 .vh tag configure timetag -foreground black -selectbackground #d9d9d9 2161 .vh tag configure linetag -foreground black -selectbackground #d9d9d9 2162 .vh tag configure nmbrtag -foreground black -selectbackground #d9d9d9 2163 .vh tag configure nametag -foreground black -selectbackground #d9d9d9 2164 .vh tag configure mttag -foreground black -selectbackground #d9d9d9 2165 .vh tag configure msgtag -foreground black -selectbackground #d9d9d9 2166 } 2167 } 2168 .tv configure -background $tvBckColor -foreground $tvFgColor \ 2169 -selectbackground $tvBckColor -selectforeground $tvFgColor 2170 .vh configure -background $vhBckColor -foreground $vhFgColor \ 2171 -insertbackground $vhInsColor 2172 $m configure -background $bckColor -foreground $fg2Color 2173 foreach item $items { 2174 $m.$item configure -background $bckColor -foreground $fg2Color \ 2175 -selectcolor $selColor 2176 } 2177if {$::tcl_platform(platform) == "unix"} { 2178 ttk::style configure TButton \ 2179 -background $bckColor \ 2180 -foreground $fg2Color 2181 ttk::style map TButton \ 2182 -background [list active $bckActColor] \ 2183 -foreground [list active $fgActColor] 2184 } 2185 ttk::style configure TEntry \ 2186 -foreground $fg3Color \ 2187 -fieldbackground $bckFldColor \ 2188 -selectbackground $bckSelColor \ 2189 -selectforeground $fgSelColor \ 2190 -insertcolor $insColor 2191 ttk::style configure TFrame \ 2192 -background $bckColor 2193 ttk::style configure TLabel \ 2194 -background $bckColor \ 2195 -foreground $fgColor 2196 ttk::style configure TLabelframe \ 2197 -background $bckColor \ 2198 -foreground $fg2Color 2199 ttk::style configure TSpinbox \ 2200 -arrowsize 15 \ 2201 -arrowcolor $arrowColor \ 2202 -background $bckColor \ 2203 -foreground $fg2Color \ 2204 -selectbackground $bck2SelColor 2205 ttk::style map TSpinbox \ 2206 -background [list active $bckActColor] \ 2207 -fieldbackground [list active $bckFldColor readonly $roColor] \ 2208 -relief [list {pressed !disabled} sunken] 2209 ttk::style configure TRadiobutton \ 2210 -indicatorcolor $indColor \ 2211 -background $bckColor \ 2212 -foreground $fgColor 2213 ttk::style map TRadiobutton \ 2214 -indicatorcolor [list selected $indSelColor pressed $indPressColor] \ 2215 -background [list active $bckActColor] \ 2216 -foreground [list active $fgActColor] 2217 ttk::style configure TCheckbutton \ 2218 -indicatorcolor $indColor \ 2219 -background $bckColor \ 2220 -foreground $fgColor 2221 ttk::style map TCheckbutton \ 2222 -indicatorcolor [list selected $indSelColor pressed $indPressColor] \ 2223 -background [list active $bckActColor] 2224 ttk::style configure TScrollbar \ 2225 -arrowsize 15 \ 2226 -arrowcolor $arrowColor \ 2227 -background $bckColor \ 2228 -troughcolor $truColor 2229 ttk::style map TScrollbar \ 2230 -arrowcolor [list active $arrowActColor] \ 2231 -background [list active $bckActColor] \ 2232 -relief [list {pressed !disabled} sunken] 2233 ttk::style configure TCombobox \ 2234 -arrowsize 15 \ 2235 -arrowcolor $arrowColor \ 2236 -background $bckColor \ 2237 -foreground $fgColor \ 2238 -fieldbackground $bckColor \ 2239 -selectbackground $bckColor \ 2240 -selectforeground $fgColor 2241 ttk::style map TCombobox \ 2242 -arrowcolor [list active $arrowActColor] \ 2243 -background [list active $bckActColor] \ 2244 -relief [list {pressed !disabled} sunken] 2245 . configure -background $bckColor 2246 2247 if $enabletheme { 2248 #ttk::style theme use $ThemeName 2249 ttk::setTheme $ThemeName 2250 } else { 2251 # Day and Night styles modify the default theme 2252 ttk::setTheme "default" 2253 } 2254} 2255 2256proc processRCfile {} { 2257 global rcfile ExitOn fontList PortableDir wmGeometry 2258 global autoSave oldAutoSave autoStart oldAutoStart 2259 global clock oldClock AltDate oldAltDate DateSepar oldDateSepar 2260 global ThemeName oldThemeName delayedMsgs 2261 global TypeGroups oldTypeGroups SelectedTypes oldSelectedTypes 2262 global LineIDGroups oldLineIDGroups SelectedLineIDs oldSelectedLineIDs 2263 global Host Port Hosts HostIndex Leading1 oldLeading1 2264 global DefaultHost DefaultPort ConfigFileHost ConfigFilePort 2265 2266 if [expr [file exists $rcfile] && [file isfile $rcfile]] { 2267 set id [open $rcfile] 2268 set data [read $id] 2269 close $id 2270 } else { 2271 set data "no data" 2272 } 2273 2274 set lines [split $data "\n"] 2275 2276 foreach line $lines { 2277 if [regexp {geometry\s+\S+\s+[0-9x]+} $line] { 2278 eval $line 2279 set wmGeometry [regsub {\w+\s+\w+\s+\S+\s+([\dx+]+)} $line {\1}] 2280 } elseif [regexp {font\s+create} $line] { 2281 eval $line 2282 } elseif [regexp {(:?fontList|clock|AltDate|DateSepar|NightMode|\ 2283 autoSave|autoStart|TypeGroups|SelectedTypes|\ 2284 LineIDGroups|SelectedLineIDs|ThemeName|\ 2285 Leading1|Host|Port|\ 2286 )\s+} $line] { 2287 eval $line 2288 } 2289 } 2290 2291 # initial values, not final values 2292 set oldHost $Host 2293 set oldPort $Port 2294 2295 # determine Host, Port and Hosts values 2296 if {$ConfigFileHost == ""} { 2297 if {$Host == ""} {set Host $DefaultHost} 2298 } else { 2299 set Host $ConfigFileHost 2300 } 2301 if {$ConfigFilePort == ""} { 2302 if {$Port == ""} {set Port $DefaultPort} 2303 } else { 2304 set Port $ConfigFilePort 2305 } 2306 2307 # host and port variables may have been replaced by the .ncid RC file 2308 # make sure there is a match against the list of hosts 2309 if {$Hosts == ""} { 2310 set Hosts "$DefaultHost:$DefaultPort" 2311 set delayedMsgs \ 2312 "$delayedMsgs\nempty Hosts list set to $DefaultHost:$DefaultPort" 2313 set HostIndex 0 2314 lassign [split [lindex $Hosts $HostIndex] ":"] Host Port 2315 write_rc_file "set Host" "set Host $Host" 2316 write_rc_file "set Port" "set Port $Port" 2317 } else { 2318 set HostIndex [lsearch -regexp $Hosts $Host:$Port] 2319 if {$HostIndex == -1} { 2320 # the config file changed since the rcfile was last updated 2321 set delayedMsgs \ 2322 "$delayedMsgs\n$Host:$Port not in list of Hosts: \"$Hosts\"" 2323 set HostIndex 0 2324 lassign [split [lindex $Hosts $HostIndex] ":"] Host Port 2325 set delayedMsgs \ 2326 "$delayedMsgs\nUsing first entry in list of hosts: $Host:$Port" 2327 } 2328 write_rc_file "set Host" "set Host $Host" 2329 write_rc_file "set Port" "set Port $Port" 2330 } 2331 2332 if {$Host != $oldHost} { 2333 # the RC file does not contain "set Host" 2334 write_rc_file "set Host" "set Host $Host" 2335 } 2336 2337 if {$Port != $oldPort} { 2338 # the RC file does not contain "set Port" 2339 write_rc_file "set Port" "set Port $Port" 2340 } 2341 2342 # remove NightMode from rcfile and add ThemeName to rcfile 2343 if {[info exists NightMode]} { 2344 if {$NightMode == 1} {set ThemeName "night"} else {set ThemeName "day"} 2345 write_rc_file "set ThemeName" "set ThemeName \"$ThemeName\"" 2346 write_rc_file "" "set NightMode" 2347 set delayedMsgs \ 2348 "$delayedMsgs\nNightMode \"$NightMode\" in rc file converted to ThemeName \"$ThemeName\"" 2349 } 2350 2351 set oldClock $clock 2352 set oldAltDate $AltDate 2353 set oldDateSepar $DateSepar 2354 set oldLeading1 $Leading1 2355 set oldThemeName $ThemeName 2356 set oldAutoSave $autoSave 2357 set oldAutoStart $autoStart 2358 set oldTypeGroups $TypeGroups 2359 set oldSelectedTypes $SelectedTypes 2360 set oldLineIDGroups $LineIDGroups 2361 set oldSelectedLineIDs $SelectedLineIDs 2362} 2363 2364proc logRCfileOldNewVarChange {verboseLevel oldVarName newVarName} { 2365 2366 # prints "rcfile and $newVarName..." 2367 upvar $oldVarName oldVarValue 2368 upvar $newVarName newVarValue 2369 if {$oldVarValue != $newVarValue} { 2370 if {[string length $oldVarValue] >30 || [string length $newVarValue] >30} { 2371 logMsg $verboseLevel "rcfile and $newVarName have been changed" 2372 logMsg $verboseLevel " from: $oldVarValue" 2373 logMsg $verboseLevel " to: $newVarValue" 2374 } else { 2375 logMsg $verboseLevel "rcfile and $newVarName have been changed from: $oldVarValue to: $newVarValue" 2376 } 2377 } 2378} 2379 2380proc do_nothing {} { 2381} 2382 2383proc do_goodbye {} { 2384 global Socket 2385 2386 if {$Socket > 0} {puts $Socket "GOODBYE"} 2387} 2388 2389proc makeWindow {} { 2390 global ExitOn 2391 global Verbose WrapLines viewTextWidth 2392 global fontList m currentFont 2393 global clock autoSave autoStart 2394 global DateSepar YearDot 2395 global Hosts HostIndex 2396 global nameREQ nmbrREQ lineREQ historyTextWidth timeWidth 2397 global lbl1 lbl2 lbl3 lbl4 lbl5 lbl6 lbl7 lbl8 2398 global wmGeometry ThemeName 2399 global TypeGroups LineIDGroups DiscoveredLineIDs 2400 2401 wm title . "Network Caller ID" 2402 wm protocol . WM_DELETE_WINDOW $ExitOn 2403 2404 set auto [expr \"$autoSave\" eq \"off\" ? \"normal\" : \"disabled\"] 2405 2406 if {$fontList == ""} {scanFonts} 2407 2408 if {[catch {font configure FixedFontH}]} { 2409 font create FixedFontH -family "$currentFont" -size 12 2410 write_rc_file "FixedFontH" \ 2411 "font create FixedFontH [font configure FixedFontH]" 2412 } 2413 if {[catch {font configure FixedFontM}]} { 2414 font create FixedFontM -family "$currentFont" -size 12 2415 write_rc_file "FixedFontM" \ 2416 "font create FixedFontM [font configure FixedFontM]" 2417 } 2418 if {[catch {font configure FixedFontP}]} { 2419 font create FixedFontP -family "$currentFont" -size 12 2420 write_rc_file "FixedFontP" \ 2421 "font create FixedFontP [font configure FixedFontP]" 2422 } 2423 2424 ttk::style configure TButton -font FixedFontP 2425 ttk::style configure TCheckbutton -font FixedFontP 2426 ttk::style configure TRadiobutton -font FixedFontP 2427 2428 # menu options: no tearoff and help menu on far right 2429 option add *tearOff 0 2430 option add *Menu.useMotifHelp 1 2431 option add *Text.relief sunken 2432 option add *Text.borderWidth 2 2433 option add *highlightThickness 1 2434# 2435 # create menubar 2436 menu .menubar 2437 . configure -menu .menubar 2438 2439 # create and place: column labels 2440 if {$clock == 24 && $DateSepar == "."} {set lbl $lbl1} 2441 if {$clock == 24 && $DateSepar == "-"} {set lbl $lbl2} 2442 if {$clock == 24 && $DateSepar == "/"} {set lbl $lbl3} 2443 if {$clock == 12 && $DateSepar == "."} {set lbl $lbl4} 2444 if {$clock == 12 && $DateSepar == "-"} {set lbl $lbl5} 2445 if {$clock == 12 && $DateSepar == "/"} {set lbl $lbl6} 2446 if {$clock == 24 && $DateSepar == "." && $YearDot == 1} {set lbl $lbl7} 2447 if {$clock == 12 && $DateSepar == "." && $YearDot == 1} {set lbl $lbl8} 2448 ttk::label .la -text $lbl -justify left -font {FixedFontH} 2449 grid .la -row 1 -sticky w -columnspan 2 2450 2451 # create File, Server, Preferences, View, Theme and Help menus 2452 set m .menubar 2453 menu $m.file 2454 menu $m.file.auto 2455 menu $m.file.startup 2456 menu $m.server 2457 menu $m.server.hosts 2458 menu $m.server.dial 2459 menu $m.server.copy 2460 menu $m.prefs 2461 menu $m.view 2462 menu $m.view.types 2463 menu $m.view.lines 2464 menu $m.theme 2465 menu $m.help 2466 $m add cascade -menu $m.file -label File -underline 0 -font FixedFontM 2467 $m add cascade -menu $m.server -label Server -underline 0 -font FixedFontM 2468 $m add cascade -menu $m.prefs -label Preferences -underline 0 -font FixedFontM 2469 $m add cascade -menu $m.view -label View -underline 0 -font FixedFontM 2470 $m add cascade -menu $m.theme -label Themes -underline 0 -font FixedFontM 2471 $m add cascade -menu $m.help -label Help -underline 0 -font FixedFontM 2472 2473 # create File menu items 2474 $m.file add command -label "Clear Log" -command clearLog -font FixedFontM 2475 $m.file add command -label "Reconnect" -command Reconnect -font FixedFontM 2476 $m.file add separator 2477 if {$::tcl_platform(platform) == "unix"} { 2478 $m.file add cascade -menu $m.file.startup -label "Auto Start" -font FixedFontM 2479 $m.file add separator 2480 } 2481 $m.file add cascade -menu $m.file.auto -label "Auto Save" -font FixedFontM 2482 $m.file add command -label "Save Size" -state $auto -command {saveSize 0} -font FixedFontM 2483 $m.file add command -label "Save Size and Position" -state $auto -command {saveSize 1} -font FixedFontM 2484 $m.file add separator 2485 $m.file add command -label Quit -command {do_goodbye; exit} -font FixedFontM 2486 2487 $m.file.auto add radiobutton -label "Size" -variable autoSave -value "size" -command {logAuto $m.file} -font FixedFontM 2488 $m.file.auto add radiobutton -label "Size and Position" -variable autoSave -value "both" -command {logAuto $m.file} -font FixedFontM 2489 $m.file.auto add radiobutton -label "Off" -variable autoSave -value "off" -command {logAuto $m.file} -font FixedFontM 2490 2491 $m.file.startup add radiobutton -label "On" -variable autoStart -value "on" -command {logStart} -font FixedFontM 2492 $m.file.startup add radiobutton -label "On with desktop notifications" -variable autoStart -value "on+alert" -command {logStart} -font FixedFontM 2493 $m.file.startup add radiobutton -label "On only desktop notifications" -variable autoStart -value "alert" -command {logStart} -font FixedFontM 2494 $m.file.startup add radiobutton -label "Off" -variable autoStart -value "off" -command {logStart} -font FixedFontM 2495 2496 # create Server menu items 2497 $m.server add cascade -menu $m.server.hosts -label "Select NCID Server" -state normal -font FixedFontM 2498 set x 0 2499 foreach i $Hosts { 2500 $m.server.hosts add radiobutton -label "$i" -variable HostIndex \ 2501 -value $x -command {logHosts} -font FixedFontM 2502 incr x 2503 } 2504 $m.server add separator 2505 $m.server add command -label "Reload alias, blacklist and whitelist files" -command { 2506 Disable $m 2507 puts $Socket "REQ: RELOAD" 2508 flush $Socket 2509 } -font FixedFontM 2510 $m.server add command -label "Update current call log" -command { 2511 global multi 2512 2513 Disable $m 2514 puts $Socket "REQ: UPDATE" 2515 flush $Socket 2516 set multi 0 2517 } -font FixedFontM 2518 $m.server add command -label "Update all call logs" -command { 2519 global multi 2520 2521 Disable $m 2522 puts $Socket "REQ: UPDATES" 2523 flush $Socket 2524 set multi 1 2525 } -font FixedFontM 2526 $m.server add command -label "Reread call log" -command { 2527 global display_line_num 2528 2529 set display_line_num 0 2530 clearLog 2531 puts $Socket "REQ: REREAD" 2532 flush $Socket 2533 } -font FixedFontM 2534 $m.server add separator 2535 $m.server add cascade -menu $m.server.dial -label "Dial Number" -state disabled -font FixedFontM 2536 $m.server.dial add command -label "Manually" -command { doDial "any" } -font FixedFontM 2537 $m.server.dial add command -label "From History" -state disabled -command { doDial "history" } -font FixedFontM 2538 $m.server add separator 2539 $m.server add command -label "Add/Modify/Remove Alias in Alias File" -state disabled -command { doList alias "" "" } -font FixedFontM 2540 $m.server add separator 2541 $m.server add command -label "Add to Blacklist File" -state disabled -command { 2542 doList black add "" 2543 } -font FixedFontM 2544 $m.server add command -label "Remove from Blacklist File" -state disabled -command { 2545 global argument 2546 doList black remove $argument 2547 } -font FixedFontM 2548 $m.server add separator 2549 $m.server add command -label "Add to Whitelist File" -state disabled -command { 2550 doList white add "" 2551 } -font FixedFontM 2552 $m.server add command -label "Remove from Whitelist File" -state disabled -command { 2553 global argument 2554 doList white remove $argument 2555 } -font FixedFontM 2556 $m.server add separator 2557 $m.server add cascade -menu $m.server.copy -label "Copy to Clipboard" -state disabled -font FixedFontM 2558 $m.server.copy add command -label "Name" -command { doClipboard 4 [lindex $dataDump 16] } -font FixedFontM 2559 $m.server.copy add command -label "Number Formatted" -command { doClipboard 1 [lindex $dataDump 13] } -font FixedFontM 2560 $m.server.copy add command -label "Number Digits" -command { doClipboard 2 [lindex $dataDump 13] } -font FixedFontM 2561 $m.server.copy add command -label "Entire Line" -command { doClipboard 3 $dataDump } -font FixedFontM 2562 2563 # create Preferences menu items 2564 $m.prefs add command -label "Font..." -command {changeFont} -font FixedFontM 2565 $m.prefs add separator 2566 $m.prefs add command -label "Date and Time..." -command {formatDT} -font FixedFontM 2567 2568 # create View menu items 2569 $m.view add cascade -menu $m.view.types -label "Line Types" -font FixedFontM 2570 $m.view add cascade -menu $m.view.lines -label "LineIDs" -font FixedFontM 2571 2572 $m.view.types add radiobutton -label "All" \ 2573 -variable TypeGroups -value 0 \ 2574 -command {logTypeGroups} -font FixedFontM 2575 $m.view.types add separator 2576 $m.view.types add radiobutton -label "Calls" \ 2577 -variable TypeGroups -value 1 \ 2578 -command {logTypeGroups} -font FixedFontM 2579 $m.view.types add radiobutton -label "Messages" \ 2580 -variable TypeGroups -value 2 \ 2581 -command {logTypeGroups} -font FixedFontM 2582 $m.view.types add radiobutton -label "Smart Phone" \ 2583 -variable TypeGroups -value 3 \ 2584 -command {logTypeGroups} -font FixedFontM 2585 $m.view.types add separator 2586 $m.view.types add radiobutton -label "Select..." \ 2587 -variable TypeGroups -value 4 \ 2588 -command {doSelectedTypes} -font FixedFontM 2589 2590 $m.view.lines add radiobutton -label "All" \ 2591 -variable LineIDGroups -value 0 \ 2592 -command {logViewLineIDs} -font FixedFontM 2593 $m.view.lines add separator 2594 $m.view.lines add radiobutton -label "Select..." \ 2595 -variable LineIDGroups -value 1 \ 2596 -command {doLineIDs} -font FixedFontM 2597 2598 # create themes menu items 2599 $m.theme add radiobutton -label "Day" \ 2600 -variable ThemeName -value "day" \ 2601 -command {logTheme} -font FixedFontP 2602 $m.theme add radiobutton -label "Night" \ 2603 -variable ThemeName -value "night" \ 2604 -command {logTheme} -font FixedFontP 2605 $m.theme add radiobutton -label "Default" \ 2606 -variable ThemeName -value "default" \ 2607 -command {logTheme} -font FixedFontP 2608 if {$::DistThemes ne "default"} {$m.theme add separator} 2609 2610 #Observed values 2611 #Windows 10: alt clam classic default vista winnative xpnative 2612 #Mac: alt clam classic default aqua 2613 #AndroWish: alt clam classic default droid 2614 #Fedora 25 cinnamon: alt clam classic default 2615 foreach t $::DistThemes { 2616 if {$t eq "default"} {continue} 2617 $m.theme add radiobutton -label [join [list [string totitle $t]]] \ 2618 -variable ThemeName -value $t \ 2619 -command {logTheme} -font FixedFontP 2620 } 2621 2622 if {$::AddonThemes != ""} { 2623 $m.theme add separator 2624 foreach t $::AddonThemes { 2625 $m.theme add radiobutton -label [join [list [string totitle $t]]] \ 2626 -variable ThemeName -value $t \ 2627 -command {logTheme} -font FixedFontP 2628 } 2629 } 2630 2631 # create Help menu item 2632 $m.help add command -label About -command {helpItem "About" $About [ncidInfo]} -font FixedFontM 2633 $m.help add command -label "Online Docs" -command {helpItem "Online Documentation" "" ""} -font FixedFontM 2634 $m.help add command -label "Field Labels" -command {helpItem "Field Labels" $fieldList ""} -font FixedFontM 2635 $m.help add command -label "Line Types" -command {helpItem "Line Types" $labList ""} -font FixedFontM 2636 $m.help add command -label "Views Window" -command {helpItem "Views Window" $viewHelp ""} -font FixedFontM 2637 $m.help add command -label "Server Menu" -command {helpItem "Server Menu Help" $serverHelp ""} -font FixedFontM 2638 $m.help add command -label "Server Options" -command serverOPT -font FixedFontM 2639 2640 # create and place: CID history scroll window 2641 if {$clock == 12} {set timeWidth 8} 2642 set historyTextWidth [expr $historyTextWidth + $timeWidth] 2643 text .vh -width $historyTextWidth -height 4 -yscrollcommand ".ys set" \ 2644 -state disabled -font {FixedFontH} -setgrid 1 -wrap $WrapLines 2645 grid [ttk::scrollbar .ys -command ".vh yview"] \ 2646 -column 1 -row 0 -sticky ns -pady 10 -padx 5 2647 grid .vh -row 2 -sticky nsew -padx 2 -pady 2 2648 grid .ys -row 2 -column 1 -sticky ns -pady 2 2649 2650 # create and place: window for view, user message 2651 ttk::frame .fr 2652 grid .fr -row 4 -columnspan 2 2653 text .tv -font {FixedFontM} -height 2 -insertwidth 0 -wrap word \ 2654 -width $viewTextWidth -yscrollcommand {.vsb set} 2655 .tv tag add strike 1.end 2656 .tv tag add blank 1.end 2657 .tv tag configure strike -overstrike 1 2658 grid .tv -row 3 -columnspan 2 2659 grid [ttk::scrollbar .vsb -command ".tv yview"] \ 2660 -column 1 -row 0 -sticky ns -pady 10 -padx 5 2661 grid .vsb -row 3 -column 1 2662 grid remove .vsb 2663 bind .tv <KeyPress> break 2664 if {$DiscoveredLineIDs != ""} {updateViewDisplay} 2665 2666 ttk::label .ml -text "Send Message: " -font {FixedFontM} 2667 ttk::entry .im -width 40 -font {FixedFontM} 2668 grid .ml .im -in .fr 2669 2670 # create and place: call and server message display 2671 ttk::label .md -textvariable Txt -font {FixedFontM} 2672 grid .md -row 5 -columnspan 2 2673 2674 grid columnconfigure . 0 -weight 1 2675 grid rowconfigure . 2 -weight 1 2676 2677 set geometry [wm grid .] 2678 wm minsize . [lindex $geometry 0] [lindex $geometry 1] 2679 update 2680 2681 switch $autoSave { 2682 "size" { 2683 $m.file entryconfigure Quit -command {do_goodbye; saveSize 0; exit} 2684 wm protocol . WM_DELETE_WINDOW {saveSize 0; $ExitOn} 2685 } 2686 "both" { 2687 $m.file entryconfigure Quit -command {do_goodbye; saveSize 1; exit} 2688 wm protocol . WM_DELETE_WINDOW {saveSize 1; $ExitOn} 2689 } 2690 } 2691 setStyles 2692 2693 wm geometry . $wmGeometry 2694 2695 logMsg $::LEVEL4 "History window font: \ 2696 [regsub {\s+\-slant.+$} [font configure FixedFontH] {}]" 2697 2698 logMsg $::LEVEL4 "Message window and display font: \ 2699 [regsub {\s+\-slant.+$} [font configure FixedFontM] {}]" 2700 2701 logMsg $::LEVEL4 "Help text: \ 2702 [regsub {\s+\-slant.+$} [font configure FixedFontP] {}]" 2703 2704 logMsg $::LEVEL4 "Window geometry set to: \ 2705 [regsub {(\d+x\d+)\+(\d+)\+(\d+)} [wm geometry .] {\1 at x=\2 y=\3}]" 2706 2707 bind . <Configure> { 2708 if {[lindex [.vh yview] 0] + [lindex [.vh yview] 1] == 1.0} { 2709 grid remove .ys 2710 } else {grid .ys} 2711 } 2712 bind .fr <Button-1> { 2713 Disable $m 2714 } 2715 bind .ml <Button-1> { 2716 Disable $m 2717 } 2718 bind .md <Button-1> { 2719 Disable $m 2720 } 2721 bind .vh <ButtonRelease-1> { 2722 .vh tag remove sel 1.0 end 2723 set first [.vh index @%x,%ylinestart] 2724 set last [.vh index @%x,%ylineend] 2725 .vh tag add sel $first $last 2726 .vh mark unset anchor 2727 .vh mark unset tk::anchor1 2728 .vh mark set insert 1.0 2729 .vh mark set current 1.0 2730 set dataDump [.vh dump -text $first $last] 2731 set select_label [string trimright [lindex $dataDump 1]] 2732 set lineREQ [string trimright [lindex $dataDump 10]] 2733 set nmbrREQ [string trimright [lindex $dataDump 13]] 2734 set nmbrREQ [string trimleft $nmbrREQ] 2735 set nameREQ [string trimright [lindex $dataDump 16]] 2736 set selected [.vh get $first $last] 2737 set nmbrREQ [regsub -all -- {[-,]} $nmbrREQ ""] 2738 if {$nameREQ eq ""} { 2739 logMsg $::LEVEL1 "$select_label nameREQ is null" 2740 set menu .menubar.server 2741 $menu entryconfigure Add*Alias* -state disabled 2742 if {!$NoGUI} { 2743 $menu entryconfigure *Blacklist* -state disabled 2744 $menu entryconfigure *Whitelist* -state disabled 2745 } 2746 } else { 2747 if {!$Try} { 2748 puts $Socket "REQ: INFO $nmbrREQ&&$nameREQ&&$lineREQ" 2749 flush $Socket 2750 logMsg $::LEVEL1 "REQ: INFO $nmbrREQ&&$nameREQ&&$lineREQ" 2751 } else { logMsg "Server not connected for a REQ: INFO" $::LEVEL1} 2752 } 2753 break 2754 } 2755} 2756 2757proc Disable {menu} { 2758 .vh tag remove sel 1.0 end 2759 set last [$menu.server index last] 2760 set found 0 2761 for {set index 0} {$index <= $last} {incr index} { 2762 set type [$menu.server type $index] 2763 # do not disable menu items before the 3rd separator 2764 if {$found == 3} { 2765 if {$type ne "separator"} { 2766 $menu.server entryconfigure $index -state disabled 2767 } 2768 } elseif {$type eq "separator"} { set found [expr $found + 1] } 2769 } 2770 # need to disable this submenu from not disabled menu entry "Dial Number" 2771 .menubar.server.dial entryconfigure From*History* -state disabled 2772} 2773 2774proc remove {menu block} { 2775 set last [$menu index last] 2776 set found [expr $block == 0 ? 1 : 0] 2777 for {set index 0} {$index <= $last} {incr index} { 2778 set type [$menu type $index] 2779 if {$found} { 2780 $menu delete $index 2781 set index [expr $index - 1] 2782 if {$type eq "separator"} { 2783 break 2784 } 2785 } elseif {$type eq "separator"} { 2786 set block [expr $block - 1] 2787 set found [expr $block == 0 ? 1 : 0] 2788 continue 2789 } 2790 } 2791} 2792 2793proc doRPLY {} { 2794 global ClientJobResult bckColor 2795 2796 toplevel .rply -background $bckColor 2797 wm title .rply "Dial Reply" 2798 wm resizable .rply 0 0 2799 2800 grid [ttk::label .rply.mesg -font FixedFontP -justify left -textvariable ClientJobResult ] -columnspan 2 -padx 12 2801 2802 grid [ttk::button .rply.ok -text "Close" -command { destroy .rply}] \ 2803 -columnspan 2 -pady 10 2804 2805 modal {.rply} 2806} 2807 2808proc doDial {dialtype} { 2809 global nmbrREQ nameREQ lineREQ DialPrefix DialLineID ClientJobResult 2810 global bckColor fgColor bckSelColor fgSelColor 2811 global Country nmbrWidth wantdial 2812 2813 toplevel .dial -background $bckColor 2814 wm title .dial "Dial" 2815 wm resizable .dial 0 0 2816 if {$DialPrefix == ""} {set dprefix "no"} else {set dprefix $DialPrefix} 2817 if {$dialtype == "history"} { 2818 set wantdial 1 2819 set ht "Request the server dial:\n\nDial: $dprefix prefix\nNmbr: $nmbrREQ\nName: $nameREQ\nLine: $lineREQ" 2820 } else { 2821 set wantdial 2 2822 set nameREQ "No Name" 2823 set ht "Request the server dial:\n\nDial: $dprefix prefix\nName: $nameREQ" 2824 } 2825 set row 1 2826 grid [ttk::label .dial.rd -justify left -font FixedFontP \ 2827 -text $ht ] \ 2828 -columnspan 2 -padx 12 -pady 10 2829 grid [ttk::label .dial.cl -justify left -font FixedFontP \ 2830 -text "Server Dial Line:"] -columnspan 2 -padx 12 -column 0 2831 set lineid_list [list $::ServerOptLineIDS] 2832 set DialLineID [lindex $lineid_list 0] 2833 grid [ttk::combobox .dial.lb -font FixedFontP -values $lineid_list \ 2834 -height 2 -textvariable DialLineID] -columnspan 2 -column 0 2835 .dial.lb set $DialLineID 2836 set row [expr $row + 2] 2837 if {$dialtype == "history"} { 2838 ttk::label .dial.mml -font FixedFontM -text "Leading 1 in number" 2839 grid [ttk::labelframe .dial.lf -labelwidget .dial.mml -labelanchor "n"] \ 2840 -columnspan 2 -column 0 -pady 5 -padx 40 2841 if {$Country == "US"} { 2842 grid [ttk::radiobutton .dial.lf.one -text "Add" \ 2843 -variable Leading1 -value "Add" -command logOne] \ 2844 -row 0 -column 0 -padx 8 2845 grid [ttk::radiobutton .dial.lf.noone -text "Remove" \ 2846 -variable Leading1 -value "Remove" -command logOne] \ 2847 -row 0 -column 1 -padx 8 2848 grid [ttk::radiobutton .dial.lf.leave -text "Leave" \ 2849 -variable Leading1 -value "Leave" -command logOne] \ 2850 -row 0 -column 2 -padx 8 2851 } 2852 } else { 2853 grid [ttk::label .dial.num -justify left -font FixedFontP \ 2854 -text "Dial Number:"] -columnspan 2 -padx 12 -column 0 2855 ttk::entry .dial.number -width $nmbrWidth -font FixedFontP 2856 grid .dial.number -sticky ew -columnspan 2 -padx 8 2857 focus .dial.number 2858 } 2859 set row [expr $row + 1] 2860 grid [ttk::frame .dial.fr] -pady 10 -columnspan 2 2861 incr row 2862 grid [ttk::label .dial.fr.lab1 -font {FixedFontM} -text "Status:"] -padx 3 2863 incr row 2864 grid [ttk::label .dial.fr.lab2 -font {FixedFontM} \ 2865 -textvariable ClientJobResult] -column 0 -padx 3 2866 incr row 2867 grid [ttk::button .dial.cancel -text "Cancel" \ 2868 -command {destroy .dial}] -row $row -pady 12 2869 grid [ttk::button .dial.call -text "Call" \ 2870 -command {DoIt "" "DIAL" "$DialPrefix[logOne]" "$nameREQ" $wantdial}] \ 2871 -row $row -column 1 2872 grid [ttk::button .dial.abort -text "ABORT" \ 2873 -command {DoIt "" "DIAL_ABORT" "$DialPrefix[logOne]" "$nameREQ" $wantdial} \ 2874 -state disabled] \ 2875 -pady 10 -row $row -column 1 2876 grid [ttk::button .dial.close -text "Close" -command { 2877 Disable .menubar 2878 destroy .dial} \ 2879 -state disabled] -columnspan 2 -row $row -pady 10 2880 grid remove .dial.close .dial.abort 2881 set ClientJobResult "Waiting for user action..." 2882 modal {.dial} 2883} 2884 2885proc doAliasType {} { 2886 global nameREQ nmbrREQ lineREQ AliasText SelAliasType 2887 global action_ replace_ alias_action line_action 2888 2889 switch $SelAliasType { 2890 NAMEDEP { 2891 set action_ $alias_action 2892 set replace_ $nameREQ 2893 set AliasText "Replace NAME: $nameREQ\nif NMBR: $nmbrREQ\nwith ALIAS entered below" 2894 if {$action_ eq "modify" } { 2895 append AliasText ",\n or clear it to remove it" 2896 incr row 2897 } 2898 } 2899 NMBRDEP { 2900 set action_ $alias_action 2901 set replace_ $nmbrREQ 2902 set AliasText "Replace NMBR: $nmbrREQ\nif NAME: $nameREQ\nwith ALIAS entered below" 2903 if {$action_ eq "modify" } { 2904 append AliasText ",\n or clear it to remove it" 2905 incr row 2906 } 2907 } 2908 NAMEONLY { 2909 set action_ $alias_action 2910 set replace_ $nameREQ 2911 if {$action_ eq "modify" } { 2912 set AliasText "Replace NAME alias: $nameREQ\nwith ALIAS entered below" 2913 append AliasText ",\n or clear it to remove it" 2914 incr row 2915 } else { 2916 set AliasText "Replace NAME: $nameREQ\nwith ALIAS entered below" 2917 } 2918 } 2919 NMBRONLY { 2920 set action_ $alias_action 2921 set replace_ $nmbrREQ 2922 if {$action_ eq "modify" } { 2923 set AliasText "Replace NMBR alias: $nmbrREQ\nwith ALIAS entered below" 2924 append AliasText ",\n or clear it to remove it" 2925 incr row 2926 } else { 2927 set AliasText "Replace NMBR: $nmbrREQ\nwith ALIAS entered below" 2928 } 2929 } 2930 NMBRNAME { 2931 set action_ $alias_action 2932 set replace_ $nmbrREQ 2933 if {$action_ eq "modify" } { 2934 set AliasText "Replace NMBRNAME alias: $nameREQ\nand NMBR: $nmbrREQ\nwith ALIAS entered below" 2935 append AliasText ",\n or clear it to remove it" 2936 incr row 2937 } else { 2938 set AliasText "Replace NAME: $nameREQ\nand NMBR: $nmbrREQ\nwith ALIAS entered below" 2939 } 2940 } 2941 LINEONLY { 2942 set action_ $line_action 2943 set replace_ $lineREQ 2944 if {$action_ eq "modify" } { 2945 set AliasText "Replace LINE alias: $lineREQ\nwith ALIAS entered below" 2946 append AliasText ",\n or clear it to remove it" 2947 incr row 2948 } else { 2949 set AliasText "Replace LINE: $lineREQ\nwith ALIAS entered below" 2950 } 2951 } 2952 } 2953 append AliasText ".\n" 2954 .confirm.lab configure -text $AliasText 2955} 2956 2957proc doList {list action which} { 2958 global entry_ action_ list_ ClientJobResult replace_ comment_ from_ 2959 global aliasList aliasTypes CIDaliasType LineAliasType SelAliasType 2960 global nameREQ nmbrREQ lineREQ AliasText alias_action line_action 2961 global nameWidth bckColor fgColor bckSelColor fgSelColor 2962 2963 toplevel .confirm -background $bckColor 2964 wm title .confirm "Confirmation" 2965 wm resizable .confirm 0 0 2966 set action_ $action 2967 set list_ $list 2968 set comment_ "" 2969 set from_ $nameREQ 2970 2971 if {$list eq "black" || $list eq "white"} { 2972 set entry [list "$nmbrREQ" "$nameREQ"] 2973 set entry_ [lindex $entry 0] 2974 if {[lindex $entry 1] eq "NO NAME" || $nameREQ eq $nmbrREQ} { 2975 set entry [lreplace $entry 1 1] 2976 } 2977 2978 if {$action eq "add"} { 2979 set _entry [join $entry "\" or \""] 2980 } elseif {$which eq "name"} { 2981 set entry_ [set _entry [lindex $entry 1]] 2982 set entry "" 2983 } else { 2984 set entry_ [set _entry [lindex $entry 0]] 2985 set entry "" 2986 } 2987 set _action [string toupper $action 0 0] 2988 set prep [expr {$action} eq "{add}" ? "{to}" : "{from}"] 2989 grid [ttk::label .confirm.lab -font FixedFontP -text "$_action \"$_entry\"\n$prep the server's ${list}list"] \ 2990 -columnspan 2 -padx 12 -pady 10 2991 if {[llength $entry] == 2} { 2992 grid [ttk::radiobutton .confirm.rb1 -text [lindex $entry 0] \ 2993 -variable entry_ \ 2994 -value [lindex $entry 0]] -pady 5 -columnspan 2 2995 grid [ttk::radiobutton .confirm.rb2 -text [lindex $entry 1] \ 2996 -variable entry_ \ 2997 -value [lindex $entry 1]] -pady 5 -columnspan 2 2998 set row 3 2999 } else { 3000 set row 1 3001 } 3002 if {$action eq "add"} { 3003 grid [ttk::label .confirm.lab1 -font FixedFontP -text "Comment:"] -padx 12 -sticky w 3004 ttk::entry .confirm.entry -width $nameWidth -font FixedFontP 3005 grid .confirm.entry -sticky ew -columnspan 2 -padx 8 3006 focus .confirm.entry 3007 set row [expr $row + 2] 3008 } 3009 } else { 3010 grid [ttk::label .confirm.list -justify left -font FixedFontP -text "NAME: $nameREQ\nNMBR: $nmbrREQ\nLINE: $lineREQ\n\nChoose the alias type:"] -columnspan 2 -padx 12 -pady 10 3011 grid [listbox .confirm.lb -font FixedFontP -listvariable aliasList \ 3012 -selectmode browse -height 0 -width 0 \ 3013 -background $bckColor -foreground $fgColor \ 3014 -selectbackground $bckSelColor -selectforeground $fgSelColor] \ 3015 -columnspan 2 3016 if {$CIDaliasType eq "NOALIAS"} { 3017 set aliasList $aliasTypes 3018 set alias_action "add" 3019 set replace_ "" 3020 } else { 3021 set aliasList "$CIDaliasType LINEONLY" 3022 set alias_action "modify" 3023 } 3024 if {$LineAliasType eq "NOALIAS"} { 3025 set line_action "add" 3026 set replace_ $lineREQ 3027 } else { 3028 set line_action "modify" 3029 set replace_ $lineREQ 3030 } 3031 .confirm.lb selection set 0 3032 set SelAliasType [.confirm.lb get [.confirm.lb curselection]] 3033 if {$SelAliasType == "LINEONLY"} {set from_ $lineREQ} 3034 set AliasText "" 3035 focus .confirm.lb 3036 grid [ttk::label .confirm.lab -justify left -font FixedFontP -text $AliasText] \ 3037 -columnspan 2 -padx 12 -pady 10 3038 ttk::entry .confirm.entry -exportselection 0 -font FixedFontP 3039 set aliaswidth [lindex $::aliasWidths \ 3040 [lsearch $aliasTypes $SelAliasType]] 3041 .confirm.entry configure -width $aliaswidth 3042 grid .confirm.entry -columnspan 2 -padx 12 -pady 10 3043 set row 4 3044 doAliasType 3045 append AliasText ".\n" 3046 if {$action_ eq "modify"} { 3047 .confirm.entry insert 0 "$replace_" 3048 } 3049 } 3050 3051 bind all <<ListboxSelect>> { 3052 global SelAliasType 3053 3054 if {[.confirm.lb curselection] eq ""} {break} 3055 set SelAliasType [.confirm.lb get [.confirm.lb curselection]] 3056 .confirm.entry configure -width [lindex $::aliasWidths \ 3057 [lsearch $::aliasTypes $SelAliasType]] 3058 focus .confirm.entry 3059 doAliasType 3060 append AliasText ".\n" 3061 .confirm.entry delete 0 end 3062 if {$action_ eq "modify"} { 3063 .confirm.entry insert end "$replace_" 3064 } 3065 } 3066 grid [ttk::frame .confirm.fr] -pady 10 -columnspan 2 -row $row 3067 incr row 3068 grid [ttk::label .confirm.fr.lab1 -font FixedFontP -text "Status:"] -padx 3 3069 grid [ttk::label .confirm.fr.lab2 -font FixedFontP -textvariable ClientJobResult] -column 0 -row 1 -padx 3 3070 grid [ttk::button .confirm.cancel -text "Cancel" -command {destroy .confirm}] -pady 10 3071 3072 if {$list eq "alias"} { 3073 grid [ttk::button .confirm.ok -text "Apply" -command { 3074 global ClientJobResult 3075 set ClientJobResult "" 3076 set replace_ [.confirm.entry get] 3077 set replace_ [string trim $replace_] 3078 if {$replace_ eq ""} { 3079 set ClientJobResult "You must enter something\nwhen adding a new alias." 3080 continue 3081 } 3082 set aliaswidth [lindex $::aliasWidths \ 3083 [lsearch $::aliasTypes $::SelAliasType]] 3084 .confirm.entry configure -width $aliaswidth 3085 if {[string length $replace_] > $aliaswidth} { 3086 .confirm.entry delete $::nameWidth end 3087 set replace_ [.confirm.entry get] 3088 set replace_ [string trim $replace_] 3089 set ClientJobResult "Alias length truncated to fit\nwindow: edit Cancel or Apply" 3090 continue 3091 } 3092 DoIt $action_ $list_ $nmbrREQ&&$replace_ "$SelAliasType&&$from_" 0}] \ 3093 -pady 10 -row $row -column 1 3094 } else { 3095 grid [ttk::button .confirm.ok -text "Apply" -command { 3096 if {$action_ eq "add"} { 3097 set comment_ [.confirm.entry get]; \ 3098 set comment_ [string trim $comment_]; \ 3099 }; \ 3100 DoIt $action_ $list_ $entry_ $comment_ 0}] \ 3101 -pady 10 -row $row -column 1 3102 } 3103 3104 incr row 3105 grid [ttk::button .confirm.close -text "Close" -command { 3106 Disable .menubar 3107 destroy .confirm} \ 3108 -state disabled ] -columnspan 2 -row $row -pady 10 3109 grid remove .confirm.close 3110 set ClientJobResult "Waiting for user action..." 3111 modal .confirm 3112} 3113 3114proc DoIt {action list entry extra wantdial} { 3115 global Socket ClientJobResult Try Dialed DialLineID 3116 3117 set Dialed $wantdial 3118 if {$Try} { 3119 set ClientJobResult "Server not connected ..." 3120 logMsg $::LEVEL1 "Server not connected for a REQ:" 3121 return 3122 } 3123 if {$Dialed > 0} { 3124 if {$Dialed == 2} {set entry [regsub -all {[^\d]} [.dial.number get] ""]} 3125 if {$list == "DIAL_ABORT"} {set Dialed 2} 3126 grid forget .dial.cancel .dial.call 3127 grid configure .dial.close -columnspan 1 3128 grid .dial.abort .dial.close 3129 puts $Socket "REQ: $list $entry&&$extra&&$DialLineID" 3130 flush $Socket 3131 logMsg $::LEVEL1 "REQ: $list $entry&&$extra&&$DialLineID" 3132 } else { 3133 set ClientJobResult "Working ..." 3134 grid forget .confirm.cancel .confirm.ok 3135 grid .confirm.close 3136 puts $Socket "REQ: $list $action \"$entry\" \"$extra\"" 3137 flush $Socket 3138 logMsg $::LEVEL1 "REQ: $list $action \"$entry\" \"$extra\"" 3139 } 3140} 3141 3142proc doClipboardPopup {title text} { 3143 3144 global ClipboardPopupCount ClipboardPopupButton ClipboardPopupTime 3145 global historyTextWidth bckColor 3146 3147 toplevel .cbp -background $bckColor 3148 wm withdraw .cbp 3149 3150 wm title .cbp $title 3151 wm resizable .cbp 0 0 3152 3153 set dismissBegin [clock clicks -milliseconds] 3154 set ClipboardPopupCount $ClipboardPopupTime 3155 3156 if {$ClipboardPopupTime > 0} {after 1000 {ClipboardPopupLoop}} 3157 set wrapwidth [expr $historyTextWidth - 30] 3158 if {[string length $text] > $wrapwidth} { 3159 logMsg $::LEVEL2 "Wrapping text of length [string length $text] to width $wrapwidth" 3160 set text [wrapParagraph $wrapwidth $text] 3161 } 3162 3163 updateClipboardPopupButton 3164 3165 set row 3 3166 grid [ttk::label .cbp.icon -image ::tk::icons::information ] \ 3167 -column 1 -padx 12 -pady 10 -row $row 3168 grid [ttk::label .cbp.text -font FixedFontP -text $text ] \ 3169 -column 2 -padx 12 -pady 10 -row $row 3170 3171 incr row 3172 incr row 3173 3174 grid [ttk::button .cbp.ok -textvariable ClipboardPopupButton -command { 3175 destroy .cbp}] \ 3176 -column 2 -pady 10 -pady 10 -row $row 3177 3178 if {$::tcl_platform(platform) != "unix"} { 3179 if {[catch {tk::PlaceWindow .cbp widget .} msg]} { logMsg $::LEVEL1 $msg} 3180 } 3181 3182 wm deiconify .cbp 3183 modal {.cbp} 3184 3185} 3186 3187proc doClipboard {flag passedData} { 3188 3189 # flag = 1 = copy phone number as shown 3190 # 2 = copy phone number digits only 3191 # 3 = copy entire line 3192 # 4 = copy name as shown 3193 3194 if {$flag != 3} {set passedData [string trim $passedData]} 3195 3196 clipboard clear 3197 switch $flag { 3198 1 - 3199 4 { 3200 clipboard append $passedData 3201 } 3202 2 { 3203 regsub -all -line {[^\d]} $passedData {} passedData 3204 clipboard append $passedData 3205 } 3206 3 { 3207 set templine "" 3208 for {set x 1} {$x < [ llength $passedData]} {incr x 3} { 3209 set tempfield [ lindex $passedData $x ] 3210 set templine "$templine$tempfield" 3211 } 3212 set passedData [string trim $templine] 3213 regsub -all -line { +} $passedData { } passedData 3214 clipboard append $passedData 3215 } 3216 } 3217 logMsg $::LEVEL2 "Copied to clipboard: $passedData" 3218 doClipboardPopup "Selected History Line" "Copied to clipboard: $passedData" 3219} 3220 3221proc updateClipboardPopupButton {} { 3222 global ClipboardPopupCount ClipboardPopupTime ClipboardPopupButton 3223 3224 if {$ClipboardPopupTime == 0} { 3225 set ClipboardPopupButton "OK" 3226 } else { 3227 set ClipboardPopupButton "Dismiss or wait $ClipboardPopupCount second" 3228 if {$ClipboardPopupCount != 1} {append ClipboardPopupButton "s" } 3229 } 3230 3231} 3232 3233proc ClipboardPopupLoop {} { 3234 global ClipboardPopupCount ClipboardPopupButton 3235 incr ClipboardPopupCount -1 3236 updateClipboardPopupButton 3237 3238 if {[winfo exists .cbp]} { 3239 if {$ClipboardPopupCount <= 0 } { 3240 .cbp.ok invoke 3241 } else { 3242 after 1000 {ClipboardPopupLoop} 3243 } 3244 } 3245 3246} 3247 3248proc doSelectedTypes {} { 3249 global labBLK labCID labHUP labMSG labMWI labNOT labOUT labPID labPUT labRID labWID 3250 global SelectedTypes oldSelectedTypes TypeGroups oldTypeGroups 3251 global t_array msgToUser bckColor 3252 3253 # convert lists to arrays 3254 array set t_array $SelectedTypes 3255 3256 set maxwidth [expr [string length $labRID] + 2] 3257 3258 set msgToUser "" 3259 3260 toplevel .ctypes -background $bckColor 3261 wm title .ctypes "Select Call and Message Types to View" 3262 wm resizable .ctypes 0 0 3263 3264 set row 3 3265 3266 grid [ttk::label .ctypes.calls -font FixedFontP \ 3267 -text "Call Types"] \ 3268 -columnspan 2 -padx 12 -pady 10 -row $row 3269 incr row 3270 incr row 3271 3272 grid [ttk::frame .ctypes.fr1] -pady 10 -columnspan 1 3273 grid [ttk::checkbutton .ctypes.fr1.blk \ 3274 -text $labBLK \ 3275 -variable t_array(BLK) -width $maxwidth] -sticky w -pady 5 -column 1 -row $row 3276 incr row 3277 3278 grid [ttk::checkbutton .ctypes.fr1.cid \ 3279 -text $labCID \ 3280 -variable t_array(CID) -width $maxwidth] -sticky w -pady 5 -column 1 -row $row 3281 incr row 3282 3283 grid [ttk::checkbutton .ctypes.fr1.hup \ 3284 -text $labHUP \ 3285 -variable t_array(HUP) -width $maxwidth] -sticky w -pady 5 -column 1 -row $row 3286 incr row 3287 3288 grid [ttk::checkbutton .ctypes.fr1.mwi \ 3289 -text $labMWI \ 3290 -variable t_array(MWI) -width $maxwidth] -sticky w -pady 5 -column 1 -row $row 3291 incr row 3292 3293 grid [ttk::checkbutton .ctypes.fr1.out \ 3294 -text $labOUT \ 3295 -variable t_array(OUT) -width $maxwidth] -sticky w -pady 5 -column 1 -row $row 3296 incr row 3297 3298 grid [ttk::checkbutton .ctypes.fr1.pid \ 3299 -text $labPID \ 3300 -variable t_array(PID) -width $maxwidth] -sticky w -pady 5 -column 1 -row $row 3301 incr row 3302 3303 grid [ttk::checkbutton .ctypes.fr1.put \ 3304 -text $labPUT \ 3305 -variable t_array(PUT) -width $maxwidth] -sticky w -pady 5 -column 1 -row $row 3306 incr row 3307 3308 grid [ttk::checkbutton .ctypes.fr1.rid \ 3309 -text $labRID \ 3310 -variable t_array(RID) -width $maxwidth] -sticky w -pady 5 -column 1 -row $row 3311 incr row 3312 3313 grid [ttk::checkbutton .ctypes.fr1.wid \ 3314 -text $labWID \ 3315 -variable t_array(WID) -width $maxwidth] -sticky w -pady 5 -column 1 -row $row 3316 incr row 3317 incr row 3318 3319 grid [ttk::label .ctypes.msgs -font FixedFontP \ 3320 -text "Message Types"] \ 3321 -columnspan 2 -padx 12 -pady 10 -row $row 3322 incr row 3323 incr row 3324 3325 grid [ttk::frame .ctypes.fr2] -pady 10 -columnspan 1 3326 grid [ttk::checkbutton .ctypes.fr2.msg \ 3327 -text $labMSG \ 3328 -variable t_array(MSG) -width $maxwidth] -sticky w -pady 5 -column 1 -row $row 3329 incr row 3330 3331 grid [ttk::checkbutton .ctypes.fr2.not \ 3332 -text $labNOT \ 3333 -variable t_array(NOT) -width $maxwidth] -sticky w -pady 5 -column 1 -row $row 3334 incr row 3335 incr row 3336 incr row 3337 incr row 3338 3339 grid [ttk::label .ctypes.msgtouser -font FixedFontP \ 3340 -textvariable msgToUser] \ 3341 -columnspan 2 -padx 12 -pady 10 -row $row 3342 3343 grid [ttk::frame .ctypes.fr3] -column 0 -pady 8 3344 grid [ttk::button .ctypes.fr3.selall -text "Select All" \ 3345 -command {array set t_array {BLK 1 CID 1 HUP 1 MWI 1 OUT 1 \ 3346 PID 1 PUT 1 RID 1 WID 1 MSG 1 NOT 1} 3347 }] -padx 12 -pady 10 -row $row 3348 3349 grid [ttk::button .ctypes.fr3.clrall -text "Clear All" -command { 3350 array set t_array {BLK 0 CID 0 HUP 0 MWI 0 OUT 0 PID 0 PUT 0 RID 0 WID 0 \ 3351 MSG 0 NOT 0} 3352 }] -column 1 -padx 12 -pady 10 -row $row 3353 3354 grid [ttk::button .ctypes.fr3.cancel -text "Cancel" -command { 3355 set TypeGroups $oldTypeGroups 3356 destroy .ctypes}] \ 3357 -column 2 -padx 12 -pady 10 -row $row 3358 3359 grid [ttk::button .ctypes.fr3.apply -text "Apply" -command { 3360 global t_array msgToUser 3361 set sum 0 3362 foreach {name value} [array get t_array] {set sum [expr $sum + $value]} 3363 if {!$sum} { 3364 set msgToUser "You must select at least one type" 3365 logMsg $::LEVEL1 $msgToUser 3366 continue 3367 } 3368 # then convert array to list 3369 set SelectedTypes [lsort -stride 2 [array get t_array]] 3370 destroy .ctypes 3371 #logTypeGroups causes call log to be re-read 3372 logTypeGroups}] \ 3373 -column 3 -padx 12 -pady 10 -row $row 3374 3375 modal {.ctypes} 3376} 3377 3378proc doLineIDs {} { 3379 global DiscoveredLineIDs LineIDGroups oldLineIDGroups 3380 global SelectedLineIDs oldSelectedLineIDs 3381 global lineREQ 3382 global SelLINE msgToUser SelHistoryLINE SelHistoryLINEIndex 3383 global bckColor fgColor bckSelColor fgSelColor 3384 3385 set msgToUser "" 3386 set SelLINE [list] 3387 3388 toplevel .clines -background $bckColor 3389 wm title .clines "Select Line Identifiers to View" 3390 wm resizable .clines 0 0 3391 3392 set oldSelectedLineIDs $SelectedLineIDs 3393 3394 set row 3 3395 3396 set viewselected $SelectedLineIDs 3397 set SelectedLineIDs "" 3398 set SelectedLineIDsIndex "" 3399 3400 foreach vs $viewselected { 3401 set index [lsearch -exact "$DiscoveredLineIDs" $vs] 3402 if {$index != -1} { 3403 lappend SelectedLineIDs $vs 3404 lappend SelectedLineIDsIndex $index 3405 } 3406 } 3407 3408 if {$SelectedLineIDsIndex == ""} {set SelectedLineIDsIndex -1} 3409 3410 # see if user selected a line in call history window 3411 set SelHistoryLINE "" 3412 set SelHistoryLINEIndex 0 3413 if {[info exists lineREQ]} { 3414 if {$lineREQ != "" } { 3415 set SelHistoryLINEIndex [lsearch -exact $DiscoveredLineIDs $lineREQ] 3416 if {$SelHistoryLINEIndex == -1} { 3417 set SelHistoryLINEIndex 0 3418 } else {set SelHistoryLINE $lineREQ} 3419 } 3420 } 3421 3422 if {[llength $DiscoveredLineIDs] > 0} { 3423 grid [listbox .clines.lb -font FixedFontP -height 4 -width 0 \ 3424 -listvariable DiscoveredLineIDs -selectmode extended \ 3425 -yscrollcommand {.clines.ys set} \ 3426 -background $bckColor -foreground $fgColor \ 3427 -selectbackground $bckSelColor -selectforeground $fgSelColor] \ 3428 -columnspan 2 3429 grid [ttk::scrollbar .clines.ys -command {.clines.lb yview}] \ 3430 -column 1 -row 0 -sticky nse -pady 1 -padx 1 3431 if {[.clines.lb index end] <= [lindex [.clines.lb configure -height] 4]} { 3432 grid remove .clines.ys 3433 } else { 3434 grid .clines.ys 3435 } 3436 if {$SelectedLineIDsIndex != -1} { 3437 foreach x $SelectedLineIDsIndex { 3438 .clines.lb selection set $x 3439 } 3440 set SelLINE {} 3441 foreach x [.clines.lb curselection] { 3442 lappend SelLINE [.clines.lb get $x] 3443 } 3444 } 3445 3446 bind all <<ListboxSelect>> { 3447 if {[info commands .clines.lb] ne ""} { 3448 set SelLINE {} 3449 foreach x [.clines.lb curselection] { 3450 lappend SelLINE [.clines.lb get $x] 3451 } 3452 if {[lindex [.clines.lb yview] 0] + \ 3453 [lindex [.clines.lb yview] 1] == 1.0} { 3454 grid remove .clines.ys 3455 } else { 3456 grid .clines.ys 3457 } 3458 } 3459 } 3460 } 3461 set row [expr [llength $DiscoveredLineIDs] + 2] 3462 3463 if {[llength $DiscoveredLineIDs] > 1} { 3464 grid [ttk::label .clines.help -justify left -font FixedFontP \ 3465 -text "Multiple selections are allowed."] \ 3466 -columnspan 2 -padx 12 -pady 10 -row $row 3467 incr row 3468 } 3469 3470 if {$SelHistoryLINE != ""} { 3471 incr row 3472 incr row 3473 grid [ttk::label .clines.call -justify left -font FixedFontP \ 3474 -text "Last selected call in history window:"] \ 3475 -columnspan 2 -padx 12 -pady 10 -row $row 3476 incr row 3477 grid [ttk::button .clines.history -text "LineID: $SelHistoryLINE" -command { 3478 global SelHistoryLINE SelHistoryLINEIndex SelLINE 3479 .clines.lb selection clear 0 end 3480 .clines.lb selection set $SelHistoryLINEIndex 3481 .clines.lb curselection 3482 set SelLINE $SelHistoryLINE 3483 logMsg $::LEVEL4 "Selected index $SelHistoryLINEIndex for SelHistoryLINE=$SelHistoryLINE" 3484 }] \ 3485 -columnspan 2 -pady 10 -row $row 3486 incr row 3487 incr row 3488 } 3489 3490 grid [ttk::label .clines.msgtouser -font FixedFontP \ 3491 -textvariable msgToUser] \ 3492 -columnspan 2 -padx 12 -pady 10 -row $row 3493 incr row 3494 incr row 3495 3496 grid [ttk::button .clines.cancel -text "Cancel" -command { 3497 global DiscoveredLineIDs LineIDGroups oldLineIDGroups 3498 set LineIDGroups $oldLineIDGroups 3499 logMsg $::LEVEL4 "Cancel: DiscoveredLineIDs contains $DiscoveredLineIDs" 3500 destroy .clines}] \ 3501 -padx 12 -row $row 3502 3503 grid [ttk::button .clines.apply -text "Apply" -command { 3504 global DiscoveredLineIDs LineIDGroups oldLineIDGroups 3505 global SelectedLineIDs oldSelectedLineIDs 3506 global SelLINE msgToUser 3507 set msgToUser "You must select at least one lineid" 3508 if {$SelLINE == ""} { 3509 logMsg $::LEVEL1 $msgToUser 3510 continue 3511 } 3512 set msgToUser "" 3513 set SelectedLineIDs $SelLINE 3514 destroy .clines 3515 #logViewLineIDs causes call log to be re-read 3516 logViewLineIDs}] \ 3517 -column 1 -padx 12 -row $row 3518 3519 modal {.clines} 3520 3521} 3522 3523proc helpItem {title passedMesg1 passedMesg2} { 3524 global Logo command Website 3525 global mesg1 mesg2 bckColor 3526 3527 set mesg1 [encoding convertfrom utf-8 $passedMesg1] 3528 set mesg2 [encoding convertfrom utf-8 $passedMesg2] 3529 3530 toplevel .hlp -background $bckColor 3531 wm title .hlp $title 3532 wm resizable .hlp 0 0 3533 3534 if [file exists $Logo] { 3535 image create photo ncid -file $Logo 3536 grid [ttk::label .hlp.img -image ncid] -columnspan 2 -padx 12 -pady 10 3537 } 3538 3539 if {$title == "About"} {set jt "center"} else {set jt "left"} 3540 3541 if {$mesg1 == ""} { 3542 grid [ttk::label .hlp.s1] 3543 grid [hyperlink .hlp.um -command [list eval exec $command "http://ncid.sourceforge.net/doc/NCID-UserManual.html" &] -text "User Manual"] -columnspan 2 3544 grid [hyperlink .hlp.mp -command [list eval exec $command "http://ncid.sourceforge.net/man/man.html" &] -text "Manual Pages"] -columnspan 2 -padx 42 3545 grid [ttk::label .hlp.s2] 3546 } else { 3547 grid [ttk::label .hlp.mesg1 -font FixedFontP -justify $jt -text $mesg1 ] -columnspan 2 -padx 12 3548 if { $title == "About" } { 3549 grid [hyperlink .hlp.web -command [list eval exec $command $Website &] -text "NCID website"] -columnspan 2 3550 grid [ttk::label .hlp.s3] 3551 } 3552 } 3553 3554 if { $mesg2 != "" } { 3555 grid [ttk::label .hlp.mesg2 -font FixedFontP -justify left -text $mesg2 ] -columnspan 2 -padx 12 3556 } 3557 3558 if { $title == "About" } { 3559 grid [ttk::button .hlp.clip -text "Copy to Clipboard" -command { 3560 clipboard clear 3561 clipboard append -- "$mesg1 $mesg2" 3562 doClipboardPopup "About" "Copied to clipboard: About window text" 3563 }] \ 3564 -columnspan 2 -pady 10 3565 } 3566 3567 grid [ttk::button .hlp.ok -text "OK" -command { 3568 Disable .menubar 3569 destroy .hlp}] \ 3570 -columnspan 2 -pady 10 3571 3572 if {$::tcl_platform(platform) != "unix"} { 3573 if {[catch {tk::PlaceWindow .hlp widget .} msg]} { logMsg $::LEVEL1 $msg} 3574 } 3575 3576 modal {.hlp} 3577} 3578 3579proc serverOPT {} { 3580 global Logo ServerOptions 3581 3582 set displayDesc "\nOptions sent to clients\n to indicate enabled:" 3583 set displayOPT "$ServerOptions" 3584 helpItem "Server Options" $displayDesc $displayOPT 3585} 3586 3587proc clearLog {} { 3588 global display_line_num Begin DiscoveredLineIDs SelHistoryLINE 3589 3590 set DiscoveredLineIDs [list] 3591 set SelHistoryLINE "" 3592 set display_line_num 0 3593 .vh configure -state normal 3594 .vh delete 1.0 end 3595 .vh yview moveto 0.0 3596 .vh configure -state disabled 3597} 3598 3599proc saveSize {flag} { 3600 global Txt 3601 3602 set save $Txt 3603 set Txt "" 3604 update 3605 3606 set geometry [wm geometry .] 3607 set Txt $save 3608 if {$flag == 0} { 3609 regexp {(\d+x\d+)\+} $geometry -> geometry 3610 } 3611 write_rc_file "geometry\\s+\\S+\\s+\[0-9x\]+" "wm geometry . $geometry" 3612 3613} 3614 3615proc write_rc_file {regexpr command} { 3616 global rcfile 3617 3618 if [file exists $rcfile] { 3619 if [file isdirectory $rcfile] { 3620 logMsg $::LEVEL1 "Unable to save data to $rcfile because it is a directory" 3621 return 3622 } 3623 set id [open $rcfile] 3624 set data [read $id] 3625 close $id 3626 set lines [lrange [split $data "\n"] 0 end-1] 3627 if {$regexpr == ""} { 3628 # command from list 3629 set lines [lsearch -all -inline -not -regexp $lines "$command"] 3630 } else { 3631 set index 0 3632 foreach line $lines { 3633 if [regexp $regexpr $line] { 3634 break 3635 } 3636 incr index 3637 } 3638 if {$index >= [llength $lines]} { 3639 lappend lines "$command" 3640 } else { 3641 lset lines $index "$command" 3642 } 3643 } 3644 set data [join $lines "\n"] 3645 set id [open $rcfile w] 3646 puts $id $data 3647 } else { 3648 set id [open $rcfile w] 3649 puts $id $command 3650 } 3651 close $id 3652} 3653 3654# Change Fonts 3655proc changeFont {} { 3656 global fontList bckColor 3657 global spinvalH spinvalM spinvalP 3658 global boldH boldM boldP 3659 3660 toplevel .f -background $bckColor 3661 wm title .f "Change Fixed Font" 3662 wm resizable .f 0 0 3663 3664 eval [concat {font create SelectionFontH} [font configure FixedFontH]] 3665 eval [concat {font create SelectionFontM} [font configure FixedFontM]] 3666 eval [concat {font create SelectionFontP} [font configure FixedFontP]] 3667 3668 set spinvalH [font configure FixedFontH -size] 3669 set boldH [font configure FixedFontH -weight] 3670 3671 set spinvalM [font configure FixedFontM -size] 3672 set boldM [font configure FixedFontM -weight] 3673 3674 set spinvalP [font configure FixedFontP -size] 3675 set boldP [font configure FixedFontP -weight] 3676 3677 set currentFont [font configure FixedFontH -family] 3678 3679 label .f.ln -font FixedFontM -text "Font Name" 3680 grid [ttk::labelframe .f.fn -labelwidget .f.ln -labelanchor "n"] -pady 8 -padx 4 -sticky "nsew" 3681 grid [ttk::combobox .f.fn.cb -font FixedFontM -values $fontList -textvariable currentFont] -pady 5 -padx [list 60 90] 3682 grid [ttk::button .f.fn.btn -text "Re-scan"] -column 1 -row 0 -pady 5 -padx 5 3683 .f.fn.cb set $currentFont 3684 3685 ttk::label .f.hw -font FixedFontH -text "History Window Font" 3686 grid [ttk::labelframe .f.fh -labelwidget .f.hw -labelanchor "n"] -column 0 -pady 8 -padx 4 -sticky "nsew" 3687 grid [ttk::checkbutton .f.fh.cb -text "Bold" -variable boldH \ 3688 -onvalue "bold" \ 3689 -offvalue "normal" \ 3690 -command {font configure SelectionFontH -weight $boldH}] \ 3691 -pady 5 -padx 60 3692 grid [ttk::label .f.fh.label -font FixedFontH -text "Size: "] -column 1 -row 0 -pady 5 -padx 40 3693 grid [ttk::spinbox .f.fh.size -from 8 -to 36 -width 3 -font FixedFontH -textvariable spinvalH \ 3694 -state readonly -command {font configure SelectionFontH -size $spinvalH}] \ 3695 -column 2 -row 0 -pady 5 -padx 5 3696 grid [ttk::label .f.hw2 -text "Sample text 0123456789" -font SelectionFontH] -column 1 -row 1 -pady [list 35 5] -padx 25 -sticky "w" 3697 3698 ttk::label .f.mml -font FixedFontM -text "Message, Menu and Label Font" 3699 grid [ttk::labelframe .f.fm -labelwidget .f.mml -labelanchor "n"] -column 0 -pady 8 -padx 4 -sticky "nsew" 3700 grid [ttk::checkbutton .f.fm.cb -text "Bold" -variable boldM \ 3701 -onvalue "bold" \ 3702 -offvalue "normal" \ 3703 -command {font configure SelectionFontM -weight $boldM}] \ 3704 -pady 5 -padx 60 3705 grid [ttk::label .f.fm.label -font FixedFontM -text "Size: "] -column 1 -row 0 -pady 5 -padx 40 3706 grid [ttk::spinbox .f.fm.size -from 8 -to 36 -width 3 \ 3707 -font FixedFontP -textvariable spinvalM \ 3708 -state readonly \ 3709 -command {font configure SelectionFontM -size $spinvalM}] \ 3710 -column 2 -row 0 -pady 5 -padx 5 3711 grid [ttk::label .f.mml2 -text "Sample text 0123456789" -font SelectionFontM] -column 1 -row 2 -pady [list 35 5] -padx 25 -sticky "w" 3712 3713 ttk::label .f.pw -font FixedFontP -text "Popup Window Font" 3714 grid [ttk::labelframe .f.fp -labelwidget .f.pw -labelanchor "n"] -column 0 -pady 8 -padx 4 -sticky "nsew" 3715 grid [ttk::checkbutton .f.fp.cb -text "Bold" -variable boldP \ 3716 -onvalue "bold" \ 3717 -offvalue "normal" \ 3718 -command {font configure SelectionFontP -weight $boldP}] \ 3719 -pady 5 -padx 60 3720 grid [ttk::label .f.fp.label -font FixedFontP -text "Size: "] -column 1 -row 0 -pady 5 -padx 40 3721 grid [ttk::spinbox .f.fp.size -from 8 -to 36 -width 3 \ 3722 -font FixedFontP -textvariable spinvalP \ 3723 -state readonly \ 3724 -command {font configure SelectionFontP -size $spinvalP}] \ 3725 -column 2 -row 0 -pady 5 -padx 5 3726 grid [ttk::label .f.pw2 -text "Sample text 0123456789" -font SelectionFontP] -column 1 -row 3 -pady [list 35 5] -padx 25 -sticky "w" 3727 3728 grid [ttk::frame .f.f] -column 0 -sticky "ew" -pady 8 3729 grid [ttk::button .f.f.cancel -text "Cancel"] -padx 12 -pady 6 3730 grid [ttk::button .f.f.apply -text "Apply"] -column 1 -row 0 -padx 12 3731 grid [ttk::button .f.f.ok -text "OK"] -column 2 -row 0 -padx 12 3732 3733 # change font family 3734 bind all <<ComboboxSelected>> { 3735 font configure SelectionFontH -family "$currentFont" 3736 font configure SelectionFontM -family "$currentFont" 3737 font configure SelectionFontP -family "$currentFont" 3738 } 3739 3740 bind TButton <ButtonRelease-1> {+ 3741 switch -regexp %W { 3742 ".ctypes.*" { break } 3743 ".clines.*" { break } 3744 ".confirm.*" { break } 3745 ".view.*" { break } 3746 ".dial.*" { break } 3747 ".dt.*" { break } 3748 ".hlp.*" { break } 3749 ".rply.*" { break } 3750 ".reply.*" { break } 3751 default { 3752 set temp [%W cget -text] 3753 switch $temp { 3754 "Cancel" { 3755 destroy .f 3756 break 3757 } 3758 "OK" - 3759 "Apply" { 3760 font configure FixedFontH -family "$currentFont" \ 3761 -size $spinvalH -weight $boldH 3762 font configure FixedFontM -family "$currentFont" \ 3763 -size $spinvalM -weight $boldM 3764 font configure FixedFontP -family "$currentFont" \ 3765 -size $spinvalP -weight $boldP 3766 logFont 3767 if {$temp eq "OK"} { 3768 destroy .f 3769 } 3770 break 3771 } 3772 "Re-scan" { 3773 .f.fn.cb configure -values {} 3774 unset fontList 3775 scanFonts 3776 .f.fn.cb configure -values $fontList 3777 break 3778 } 3779 } 3780 } 3781 } 3782 } 3783 3784 modal {.f} 3785 3786 font delete SelectionFontH 3787 font delete SelectionFontM 3788 font delete SelectionFontP 3789} 3790 3791proc logFont {} { 3792 set fonth "[font configure FixedFontH]" 3793 set fontm "[font configure FixedFontM]" 3794 set fontp "[font configure FixedFontP]" 3795 3796 write_rc_file "FixedFontH" "font create FixedFontH $fonth" 3797 write_rc_file "FixedFontM" "font create FixedFontM $fontm" 3798 write_rc_file "FixedFontP" "font create FixedFontP $fontp" 3799 3800 logMsg $::LEVEL1 "history window font (FixedFontH) has been saved after command: $fonth" 3801 logMsg $::LEVEL1 "message window and display font (FixedFontM) has been saved after command: $fontm" 3802 logMsg $::LEVEL1 "help text font (FixedFontP) has been saved after command: $fontp" 3803} 3804 3805proc logOne {} { 3806 global Leading1 oldLeading1 nmbrREQ Country 3807 3808 if {$Leading1 != $oldLeading1} { 3809 logRCfileOldNewVarChange $::LEVEL2 oldLeading1 Leading1 3810 set oldLeading1 $Leading1 3811 write_rc_file "set Leading1" "set Leading1 \"$Leading1\"" 3812 } 3813 3814 set dialnmbr $nmbrREQ 3815 if {$Country == "US"} { 3816 switch $Leading1 { 3817 "Leave" { 3818 } 3819 "Add" { 3820 if {[regexp {^91?} $dialnmbr] && [string length $dialnmbr] >= 11} { 3821 regsub {^91?} $dialnmbr {91} dialnmbr 3822 } else { 3823 regsub {^1?} $dialnmbr {1} dialnmbr 3824 } 3825 } 3826 "Remove" { 3827 if {[regexp {^91} $dialnmbr] && [string length $dialnmbr] == 12} { 3828 regsub {^91} $dialnmbr {9} dialnmbr 3829 } else { 3830 regsub {^1} $dialnmbr {} dialnmbr 3831 } 3832 } 3833 } 3834 } 3835 return $dialnmbr 3836} 3837 3838proc formatDT {} { 3839 global bckColor 3840 3841 toplevel .dt -background $bckColor 3842 wm title .dt "Date and Time Formats" 3843 wm resizable .dt 0 0 3844 3845 grid [ttk::label .dt.s1] 3846 grid [ttk::radiobutton .dt.12 -text "12 hour time" -variable clock -value 12 -command {logClock .vh}] -columnspan 2 3847 grid [ttk::radiobutton .dt.24 -text "24 hour time" -variable clock -value 24 -command {logClock .vh}] -columnspan 2 -rowspan 2 3848 3849 grid [ttk::label .dt.s2] 3850 grid [ttk::radiobutton .dt.mm -text "Date: MM DD YYYY" -variable AltDate -value 0 -command {logDate .vh}] -columnspan 2 -padx 12 3851 grid [ttk::radiobutton .dt.dd -text "Date: DD MM YYYY" -variable AltDate -value 1 -command {logDate .vh}] -columnspan 2 -padx 12 -rowspan 2 3852 3853 grid [ttk::label .dt.s3] 3854 grid [ttk::radiobutton .dt.s -text "Date Separator: /" -variable DateSepar -value "/" -command {logDate .vh}] -columnspan 2 -padx 12 3855 grid [ttk::radiobutton .dt.d -text "Date Separator: -" -variable DateSepar -value "-" -command {logDate .vh}] -columnspan 2 -padx 12 3856 grid [ttk::radiobutton .dt.p -text "Date Separator: ." -variable DateSepar -value "." -command {logDate .vh}] -columnspan 2 -padx 12 3857 3858 grid [ttk::label .dt.s4] 3859 grid [ttk::button .dt.ok -text "OK" -command { 3860 Disable .menubar 3861 destroy .dt}] \ 3862 -columnspan 2 -pady 10 3863 3864 modal {.dt} 3865} 3866 3867proc logDate {widget} { 3868 global AltDate oldAltDate DateSepar oldDateSepar YearDot clock Socket display_line_num lbl1 lbl2 lbl3 lbl4 lbl5 lbl6 lbl7 lbl8 historyTextWidth 3869 3870 set dateflag 0 3871 if {$AltDate != $oldAltDate} { 3872 logRCfileOldNewVarChange $::LEVEL2 oldAltDate AltDate 3873 set oldAltDate $AltDate 3874 set dateflag 1 3875 write_rc_file "set AltDate" "set AltDate $AltDate" 3876 } elseif {$DateSepar != $oldDateSepar} { 3877 logRCfileOldNewVarChange $::LEVEL2 oldDateSepar DateSepar 3878 set oldDateSepar $DateSepar 3879 write_rc_file "set DateSepar" "set DateSepar $DateSepar" 3880 } else { return } 3881 3882 $widget configure -state normal 3883 for {set line 0} {1} {incr line} { 3884 set temp [$widget dump -text "1.0 + $line l" "1.0 + $line l lineend"] 3885 if {$temp eq ""} {break} 3886 # do not check for END or RLY in next line because these are ignored in this script 3887 if {![regexp {^(?:BLK|CID|HUP|MSG|MWI|NOT|OUT|PID|PUT|RID|WID)} [lindex $temp 1]]} { 3888 continue 3889 } 3890 # MSG lines may have no date or time, if the llength is 8 3891 if {[llength $temp] < 10} {continue} 3892 set date [lindex $temp 4] 3893 set start [lindex $temp 5] 3894 set stop [lindex $temp 8] 3895 set f1 [string range $date 0 1] 3896 set f2 [string range $date 3 4] 3897 set f3 [string range $date 6 9] 3898 if {$dateflag} { 3899 set date "$f2$DateSepar$f1$DateSepar$f3" 3900 } else { 3901 set date "$f1$DateSepar$f2$DateSepar$f3" 3902 } 3903 $widget insert "$stop - 1 c" "$date" 3904 $widget delete "$start" "$stop - 1 c" 3905 } 3906 3907 if {$clock == 24 && $DateSepar == "."} {set lbl $lbl1} 3908 if {$clock == 24 && $DateSepar == "-"} {set lbl $lbl2} 3909 if {$clock == 24 && $DateSepar == "/"} {set lbl $lbl3} 3910 if {$clock == 12 && $DateSepar == "."} {set lbl $lbl4} 3911 if {$clock == 12 && $DateSepar == "-"} {set lbl $lbl5} 3912 if {$clock == 12 && $DateSepar == "/"} {set lbl $lbl6} 3913 if {$clock == 24 && $DateSepar == "." && $YearDot == 1} {set lbl $lbl7} 3914 if {$clock == 12 && $DateSepar == "." && $YearDot == 1} {set lbl $lbl8} 3915 3916 if $YearDot { 3917 if {$Socket > 0} { 3918 set display_line_num 0 3919 clearLog 3920 puts $Socket "REQ: REREAD" 3921 flush $Socket 3922 } 3923 .la configure -text $lbl 3924 logMsg $::LEVEL1 "History Text Field Width changed to: $historyTextWidth characters" 3925 $widget configure -width $historyTextWidth 3926 set geometry [wm grid .] 3927 wm minsize . [lindex $geometry 0] [lindex $geometry 1] 3928 update 3929 $widget configure -state disabled 3930 } 3931} 3932 3933proc logTypeGroups {} { 3934 global TypeGroups oldTypeGroups SelectedTypes oldSelectedTypes 3935 global Socket display_line_num 3936 3937 set changeflag 0 3938 3939 if {$TypeGroups != $oldTypeGroups} { 3940 logRCfileOldNewVarChange $::LEVEL2 oldTypeGroups TypeGroups 3941 set oldTypeGroups $TypeGroups 3942 set changeflag 1 3943 updateViewDisplay 3944 write_rc_file "set TypeGroups" "set TypeGroups $TypeGroups" 3945 } 3946 if {$SelectedTypes != $oldSelectedTypes} { 3947 logRCfileOldNewVarChange $::LEVEL2 oldSelectedTypes SelectedTypes 3948 set oldSelectedTypes $SelectedTypes 3949 set changeflag 1 3950 updateViewDisplay 3951 write_rc_file "set SelectedTypes" "set SelectedTypes \{$SelectedTypes\}" 3952 } 3953 3954 if {$changeflag && $Socket > 0} { 3955 set display_line_num 0 3956 clearLog 3957 puts $Socket "REQ: REREAD" 3958 flush $Socket 3959 } 3960} 3961 3962proc logViewLineIDs {} { 3963 global DiscoveredLineIDs LineIDGroups oldLineIDGroups 3964 global SelectedLineIDs oldSelectedLineIDs 3965 global Socket display_line_num 3966 3967 set changeflag 0 3968 3969 if {$LineIDGroups != $oldLineIDGroups} { 3970 logRCfileOldNewVarChange $::LEVEL2 oldLineIDGroups LineIDGroups 3971 set oldLineIDGroups $LineIDGroups 3972 set changeflag 1 3973 write_rc_file "set LineIDGroups" "set LineIDGroups $LineIDGroups" 3974 if {$LineIDGroups == 0 && $SelectedLineIDs != $DiscoveredLineIDs} { 3975 set SelectedLineIDs $DiscoveredLineIDs 3976 } 3977 updateViewDisplay 3978 } 3979 3980 if {$SelectedLineIDs != $oldSelectedLineIDs} { 3981 logRCfileOldNewVarChange $::LEVEL2 oldSelectedLineIDs SelectedLineIDs 3982 set oldSelectedLineIDs $SelectedLineIDs 3983 set changeflag 1 3984 updateViewDisplay 3985 write_rc_file "set SelectedLineIDs" "set SelectedLineIDs \"$SelectedLineIDs\"" 3986 } 3987 3988 if {$changeflag && $Socket > 0} { 3989 set display_line_num 0 3990 clearLog 3991 puts $Socket "REQ: REREAD" 3992 flush $Socket 3993 } 3994 3995} 3996 3997proc logHosts {} { 3998 global Hosts HostIndex Host Port oldHost oldPort SelHistoryLINE 3999 global ChangeHostFlag SelectedLineIDs LineIDGroups TypeGroups 4000 global ServerOptions 4001 4002 logMsg $::LEVEL2 "logHosts:" 4003 4004 set ChangeHostFlag 0 4005 lassign [split [lindex $Hosts $HostIndex] ":"] Host Port 4006 #logMsg $::LEVEL2 "Setting Host=$Host and Port=$Port by extracting HostIndex=$HostIndex from Hosts=$Hosts" 4007 logMsg $::LEVEL2 " HostIndex=$HostIndex hosts=$Hosts" 4008 logMsg $::LEVEL2 " host=$Host oldHost=$oldHost Port=$Port oldPort=$oldPort" 4009 if {$oldHost != $Host || $oldPort != $Port} { 4010 if {$oldHost != $Host} { 4011 logRCfileOldNewVarChange $::LEVEL2 oldHost Host 4012 set oldHost $Host 4013 set ChangeHostFlag 1 4014 write_rc_file "set Host" "set Host $Host" 4015 } 4016 if {$oldPort != $Port} { 4017 logRCfileOldNewVarChange $::LEVEL2 oldPort Port 4018 set oldPort $Port 4019 set ChangeHostFlag 1 4020 write_rc_file "set Port" "set Port $Port" 4021 } 4022 } 4023 4024 if {$ChangeHostFlag} { 4025 set LineIDGroups 0 4026 write_rc_file "set LineIDGroups" "set LineIDGroups 0" 4027 set TypeGroups 0 4028 write_rc_file "set TypeGroups" "set TypeGroups 0" 4029 set SelectedLineIDs "" 4030 set ServerOptions "" 4031 clearLog 4032 Reconnect 4033 } 4034} 4035 4036# when switching between multiple servers, make it obvious in the log file 4037proc logServerAddress {} { 4038 global Host Port 4039 4040 set bannerFill "=" 4041 set bannerText "$bannerFill Server address: $Host:$Port $bannerFill" 4042 set bannerStars [string repeat $bannerFill [string length $bannerText]] 4043 logMsg $::LEVEL1 "$bannerStars" 4044 logMsg $::LEVEL1 "$bannerText" 4045 logMsg $::LEVEL1 "$bannerStars" 4046} 4047 4048proc processLineID {lineid} { 4049 global DiscoveredLineIDs SelectedLineIDs 4050 4051 set ret 0 4052 4053 # determine if DiscoveredLineIDs needs to be updated 4054 if {$lineid == ""} {set lineid "No-LineID"} 4055 if {[lsearch -exact $DiscoveredLineIDs "$lineid"] == -1} { 4056 lappend DiscoveredLineIDs "$lineid" 4057 } 4058 4059 # check if lineid is in SelectedLineIDs 4060 if {$SelectedLineIDs == ""} { 4061 set ret 1 4062 } else { 4063 foreach id_ $SelectedLineIDs {if {$id_ == $lineid} {set ret 1; break}} 4064 } 4065 4066 return $ret 4067} 4068 4069proc updateViewDisplay {} { 4070 global TypeGroups SelectedTypes 4071 global LineIDGroups SelectedLineIDs DiscoveredLineIDs 4072 global SelectedAllTypes SelectedCalls SelectedMessages SelectedSmartPhone 4073 4074 set selectview [list] 4075 .tv delete 1.0 2.end 4076 switch $TypeGroups { 4077 0 { 4078 set selectview $SelectedAllTypes; .tv insert 1.end "View All Types:" 4079 } 4080 1 { 4081 set selectview $SelectedCalls; .tv insert 1.end "View Call Types:" 4082 } 4083 2 { 4084 set selectview $SelectedMessages; .tv insert 1.end "View Message Types:" 4085 } 4086 3 { 4087 set selectview $SelectedSmartPhone;.tv insert 1.end "View Smart Phone Types:" 4088 } 4089 4 { 4090 set selectview $SelectedTypes; .tv insert 1.end "View Selected Types: " 4091 } 4092 } 4093 if {$selectview == ""} { 4094 .tv insert 1.end "View All Types: " 4095 set SelectedTypes "$SelectedAllTypes" 4096 } else {set SelectedTypes "$selectview"} 4097 foreach {type flag} $SelectedTypes { 4098 if {$flag == 1} { 4099 .tv insert 1.end " $type" "blank" 4100 } else { 4101 .tv insert 1.end " " "blank" 4102 .tv insert 1.end "$type" "strike $type" 4103 } 4104 } 4105 4106 if {$SelectedLineIDs == ""} { 4107 set SelectedLineIDs $DiscoveredLineIDs 4108 } else { 4109 set viewselected $SelectedLineIDs 4110 set SelectedLineIDs "" 4111 foreach vs $viewselected { 4112 set index [lsearch -exact "$DiscoveredLineIDs" $vs] 4113 if {$index != -1} { 4114 lappend SelectedLineIDs $vs 4115 } 4116 } 4117 } 4118 4119 .tv insert 1.end "\n" 4120 if {$LineIDGroups == 0} { 4121 .tv insert 2.end "View All LineIDs: $SelectedLineIDs" 4122 } else { 4123 .tv insert 2.end "View Selected LineIDs:" 4124 set lineids [list] 4125 4126 # Setup array for viewing lineids 4127 foreach lineid $DiscoveredLineIDs { 4128 lappend lineids $lineid 0 4129 } 4130 4131 # determine which lineids are wanted for viewing 4132 foreach lineid $SelectedLineIDs { 4133 if {[set pos [lsearch -exact $lineids $lineid]] != -1} { 4134 set pos1 [expr $pos + 1] 4135 set lineids "[lreplace $lineids $pos1 $pos1 1]" 4136 } 4137 } 4138 4139 # view each lineid 4140 foreach {lineid value} $lineids { 4141 # need to enclose lineid with {} again 4142 if {[regexp {\s} $lineid]} {set lineid "{$lineid}"} 4143 # determine when to strikeout a lineid 4144 if {$value == 1} { 4145 .tv insert 2.end " $lineid" "blank" 4146 } else { 4147 .tv insert 2.end " " "blank" 4148 .tv insert 2.end "$lineid" "strike $lineid" 4149 } 4150 } 4151 } 4152 update 4153 if {[lindex [.tv yview] 0] + [lindex [.tv yview] 1] != 1.0} { 4154 grid .vsb} else {grid remove .vsb} 4155} 4156 4157proc logTheme {} { 4158 global oldThemeName ThemeName 4159 global Socket display_line_num 4160 4161 if {$ThemeName != $oldThemeName} { 4162 logRCfileOldNewVarChange $::LEVEL2 oldThemeName ThemeName 4163 set oldThemeName $ThemeName 4164 write_rc_file "set ThemeName" "set ThemeName \"$ThemeName\"" 4165 4166 setStyles 4167 if {$Socket > 0} { 4168 set display_line_num 0 4169 clearLog 4170 puts $Socket "REQ: REREAD" 4171 flush $Socket 4172 } 4173 } 4174} 4175 4176proc logClock {widget} { 4177 global clock oldClock DateSepar YearDot Socket display_line_num lbl1 lbl2 lbl3 lbl4 lbl5 lbl6 lbl7 lbl8 historyTextWidth 4178 4179 if {$clock == $oldClock} { return } 4180 #not using logRCfileOldNewVarChange here as next line is more user friendly 4181 logMsg $::LEVEL2 "rcfile and Time display have been changed from: $oldClock to: $clock hours" 4182 set oldClock $clock 4183 write_rc_file "set clock" "set clock $clock" 4184 $widget configure -state normal 4185 for {set line 0} {1} {incr line} { 4186 set temp [$widget dump -text "1.0 + $line l" "1.0 + $line l lineend"] 4187 if {$temp eq ""} {break} 4188 # do not check for END or RLY in next line because these are ignored in this script 4189 if {![regexp {^(?:BLK|CID|HUP|MSG|MWI|NOT|OUT|PID|PUT|RID|WID)} [lindex $temp 1]]} { 4190 continue 4191 } 4192 # MSG lines may have no date or time, if so the llength is 8 4193 if {[llength $temp] < 10} {continue} 4194 set time [lindex $temp 7] 4195 set start [lindex $temp 8] 4196 set stop [lindex $temp 11] 4197 if {$clock == 12} { 4198 set hours [string range $time 0 1] 4199 set minutes [string range $time 3 4] 4200 set time [convertTo12 $hours $minutes] 4201 } else { 4202 set hours [string range $time 0 1] 4203 set minutes [string range $time 3 4] 4204 set AmPm [string range $time 6 7] 4205 set time [convertTo24 $hours $minutes $AmPm] 4206 } 4207 $widget insert "$stop - 1 c" "$time" 4208 $widget delete "$start" "$stop - 1 c" 4209 } 4210 4211 if {$clock == 24 && $DateSepar == "."} {set lbl $lbl1} 4212 if {$clock == 24 && $DateSepar == "-"} {set lbl $lbl2} 4213 if {$clock == 24 && $DateSepar == "/"} {set lbl $lbl3} 4214 if {$clock == 12 && $DateSepar == "."} {set lbl $lbl4} 4215 if {$clock == 12 && $DateSepar == "-"} {set lbl $lbl5} 4216 if {$clock == 12 && $DateSepar == "/"} {set lbl $lbl6} 4217 if {$clock == 24 && $DateSepar == "." && $YearDot == 1} {set lbl $lbl7} 4218 if {$clock == 12 && $DateSepar == "." && $YearDot == 1} {set lbl $lbl8} 4219 4220 if {$Socket > 0} { 4221 set display_line_num 0 4222 clearLog 4223 puts $Socket "REQ: REREAD" 4224 flush $Socket 4225 } 4226 .la configure -text $lbl 4227 logMsg $::LEVEL1 "History Text Field Width changed to: $historyTextWidth characters" 4228 $widget configure -width $historyTextWidth 4229 set geometry [wm grid .] 4230 wm minsize . [lindex $geometry 0] [lindex $geometry 1] 4231 update 4232 $widget configure -state disabled 4233} 4234 4235proc logAuto {menu} { 4236 global ExitOn autoSave oldAutoSave m 4237 4238 if {$autoSave eq $oldAutoSave} { return } 4239 set oldAutoSave $autoSave 4240 write_rc_file "set autoSave" "set autoSave \"$autoSave\"" 4241 switch $autoSave { 4242 "size" { 4243 set temp "save size only" 4244 $menu entryconfigure *Size -state disabled 4245 $menu entryconfigure *Position -state disabled 4246 $menu entryconfigure Quit -command {do_goodbye; saveSize 0; exit} 4247 wm protocol . WM_DELETE_WINDOW {do_goodbye; saveSize 0; $ExitOn} 4248 } 4249 "both" { 4250 set temp "save size and position" 4251 $menu entryconfigure *Size -state disabled 4252 $menu entryconfigure *Position -state disabled 4253 $menu entryconfigure Quit -command {do_goodbye; saveSize 1; exit} 4254 wm protocol . WM_DELETE_WINDOW {saveSize 1; $ExitOn} 4255 } 4256 "off" { 4257 set temp "off" 4258 $menu entryconfigure *Size -state normal 4259 $menu entryconfigure *Position -state normal 4260 $menu entryconfigure Quit -command {do_goodbye; exit} 4261 wm protocol . WM_DELETE_WINDOW $ExitOn 4262 } 4263 } 4264 logMsg $::LEVEL2 "rcfile and autoSave have been set to $temp" 4265} 4266 4267proc logStart {} { 4268 global autoStart oldAutoStart dtfile asfile 4269 4270 if {$autoStart eq $oldAutoStart} { return } 4271 set oldAutoStart $autoStart 4272 switch $autoStart { 4273 "on" { 4274 file copy -force $dtfile $asfile 4275 } 4276 "on+alert" { 4277 set in [open $dtfile r] 4278 set out [open $asfile w] 4279 while {[gets $in line] != -1} { 4280 regsub {NCID client} $line {NCID client with ncid-alert} line 4281 regsub {ID\) client} $line {ID) client with desktop notifications} line 4282 regsub {Exec=ncid} $line {Exec=ncid --module ncid-alert} line 4283 puts $out $line 4284 } 4285 close $in 4286 close $out 4287 } 4288 "alert" { 4289 set in [open $dtfile r] 4290 set out [open $asfile w] 4291 while {[gets $in line] != -1} { 4292 regsub {NCID client} $line {NCID Alert} line 4293 regsub {NCID \(Network Caller ID\) client} $line {Send NCID call or message desktop notifications} line 4294 regsub {Exec=ncid} $line {Exec=ncid --no-gui --module ncid-alert} line 4295 puts $out $line 4296 } 4297 close $in 4298 close $out 4299 } 4300 "off" { 4301 file delete $asfile 4302 } 4303 } 4304 write_rc_file "set autoStart" "set autoStart \"$autoStart\"" 4305 logMsg $::LEVEL2 "rcfile and autoStart have been set to $autoStart" 4306} 4307 4308# Handle MSG from GUI 4309proc handleGUIMSG {} { 4310 4311 # get MSG and clear text input box 4312 set line [.im get] 4313 .im delete 0 end 4314 # get rid of non-printable characters at start/end of string 4315 set line [string trim $line] 4316 # send MSG to server, if $line not empty 4317 if {[string length $line] > 0} {handleMSG $line} 4318} 4319 4320# Handle MSG sent to server 4321proc handleMSG {msg} { 4322 global Socket LoginName LineName 4323 4324 puts $Socket "MSG: $msg ###NAME*$LoginName*LINE*$LineName" 4325 flush $Socket 4326} 4327 4328# Handle verbosity levels 4329proc logMsg {level msg} { 4330 global Verbose LogChan 4331 4332 if {$Verbose >= $level} { 4333 puts "$msg" 4334 if {$LogChan != ""} { 4335 set systemTime [clock seconds] 4336 puts $LogChan "\[[clock format $systemTime -format "%m/%d %H:%M"]\] $msg" 4337 } 4338 } 4339} 4340 4341# https://stackoverflow.com/a/34221864 4342proc logArray {verboseLevel heading a {pattern *}} { 4343 upvar 1 $a array 4344 if {![array exists array]} { 4345 return -code error "\"$a\" isn't an array" 4346 } 4347 set maxl 0 4348 set names [lsort [array names array $pattern]] 4349 foreach name $names { 4350 if {[string length $name] > $maxl} { 4351 set maxl [string length $name] 4352 } 4353 } 4354 set maxl [expr {$maxl + [string length $a] + 2}] 4355 set indent "" 4356 if {$heading != ""} { 4357 logMsg $verboseLevel $heading 4358 set indent " " 4359 } 4360 foreach name $names { 4361 set nameString [format %s(%s) $a $name] 4362 logMsg $verboseLevel [format "%s$%-*s = %s" "$indent" $maxl $nameString $array($name)] 4363 } 4364} 4365 4366 4367# handle a PID file, if it can not be created, ignore it 4368proc doPID {} { 4369 global PIDfile 4370 4371 if {$PIDfile != ""} { 4372 set activepid "" 4373 set PIDdir [file dirname $PIDfile] 4374 if {[file writable $PIDfile]} { 4375 # get the pid's on the first line of the pidfile 4376 set chan [open $PIDfile r ] 4377 gets $chan line 4378 close $chan 4379 # save any active pid 4380 foreach p $line { 4381 if {[file exists /proc/$p]} {set activepid "$p "} 4382 } 4383 # truncate the pidfile 4384 set chan [open $PIDfile w ] 4385 if {$activepid == ""} { 4386 # write current PID into pidfile 4387 puts $chan [pid] 4388 } else { 4389 # write active PID's and current PID into pidfile 4390 puts $chan "$activepid [pid]" 4391 } 4392 close $chan 4393 } elseif {[file writable $PIDdir]} { 4394 # create the pidfile 4395 set chan [open $PIDfile "CREAT WRONLY" 0644] 4396 puts $chan [pid] 4397 close $chan 4398 4399 } 4400 logMsg $::LEVEL1 "Using pidfile: $PIDfile" 4401 } else {logMsg $::LEVEL1 "Not using a PID file"} 4402} 4403 4404# handle log file, if it can not be created, ignore it 4405proc doLogOpen {} { 4406 global LogEnable LogDir LogChan LogStatus LogFile 4407 4408 set access "CREAT WRONLY TRUNC" 4409 switch $LogEnable { 4410 1 { 4411 # create embed process ID in file name 4412 set LogFile [file normalize [file join $LogDir "ncid-client-[pid].log"]] 4413 set LogStatus "Log File: $LogFile\n enabled - process ID" 4414 } 4415 2 { 4416 # create/overwrite, do not embed process ID in file name 4417 set log_file ncid-client.log 4418 if {[machine platform] == "windows"} {set log_file ncid-windows.log} 4419 if {[machine platform] == "unix"} {set log_file "ncid-[info hostname].log"} 4420 if {[machine platform] == "android"} {set log_file ncid-androwish.log} 4421 if {[machine os] == "Darwin"} {regsub {^ncid} $log_file {ncid-mac} log_file} 4422 set LogFile [file normalize [file join $LogDir $log_file]] 4423 set LogStatus "Log File: $LogFile\n enabled - overwrite" 4424 } 4425 default { 4426 # this should never happen 4427 set LogStatus "LogEnable out of range: $LogEnable" 4428 set LogEnable 0 4429 } 4430 } 4431 4432 if {$LogEnable > 0} { 4433 if {[catch {set LogChan [open $LogFile $access "0644"]} failmsg]} { 4434 # logfile open failed 4435 set LogStatus "$failmsg" 4436 set LogEnable 0 4437 } else { 4438 fconfigure $LogChan -buffering line 4439 } 4440 } 4441 set LogStatus [regsub {/.*/} $LogStatus ""] 4442} 4443 4444proc scanFonts {} { 4445 global fontList currentFont 4446 4447 set numberFonts 0 4448 set numberFixed 0 4449 # find a fixed-width font and use it 4450 foreach family [font families] { 4451 incr numberFonts 4452 4453 # Skip Bauhaus9 on Apple Mac -- triggers wish error: 4454 # CoreText: Invalid 'kern' Table In CTFont <name: Bauhaus93.... 4455 if {$family == "Bauhaus 93"} { 4456 logMsg $::LEVEL4 "skipping fixed font: $family" 4457 continue 4458 } 4459 4460 # Skip '.LastResort' on Apple Mac -- garbles all text 4461 if {$family == ".LastResort"} { 4462 logMsg $::LEVEL4 "skipping fixed font: $family" 4463 continue 4464 } 4465 4466 # skip Emoji fonts, color ones cause "X Error of failed request" 4467 if {[regexp {Emoji} $family]} { 4468 logMsg $::LEVEL4 "skipping fixed font: $family" 4469 continue 4470 } 4471 4472 # Microsoft has duplicate fonts that start with @ 4473 if {[regexp {^@} $family]} { 4474 logMsg $::LEVEL4 "skipping fixed font: $family" 4475 continue 4476 } 4477 4478 if {[font metrics \"$family\" -fixed]} { 4479 incr numberFixed 4480 logMsg $::LEVEL4 "detected fixed font $family" 4481 lappend fontList $family 4482 } 4483 } 4484 # sort and remove duplicates 4485 set fontList [lsort -dictionary -unique $fontList] 4486 4487 set currentFont [lindex $fontList 0] 4488 logMsg $::LEVEL1 "current font set to: $currentFont" 4489 logMsg $::LEVEL1 "$numberFixed fixed fonts out of $numberFonts fonts" 4490 write_rc_file "fontList " "set fontList \"$fontList\"" 4491} 4492 4493proc modal {window} { 4494 wm transient $window . 4495 4496 # Tk Command: tkwait visibility 4497 # https://www.tcl.tk/man/tcl/TkCmd/tkwait.htm 4498 # Waits for a change in the visibility state of a window as indicated by a <VisibilityNotify> event. 4499 # This is typically used to wait for a newly-created window to appear on the screen before taking some action. 4500 # https://stackoverflow.com/questions/8929031/grabbing-a-new-window-in-tcl-tk 4501 # This prevents the error from sometimes appearing: 4502 # RGError: grab failed: window not viewable 4503 # 4504 # Tk Command: wininfo viewable 4505 # https://www.tcl.tk/man/tcl/TkCmd/winfo.htm 4506 # http://wiki.tcl.tk/10013 4507 # Needed for (Windows, OSX/Aqua) because <VisibilityNotify> events are never delivered. 4508 # On a windows platform, tkwait visibility does not return on a visable vindow. 4509 if {![winfo viewable $window]} { tkwait visibility $window } 4510 4511 grab $window 4512 4513 # Resolves the lack of focus on a newly created window 4514 focus $window 4515 4516 wm protocol $window WM_DELETE_$window {grab release $window; destroy $window} 4517 raise $window 4518 tkwait window $window 4519} 4520 4521# Hyperlink Widget: https://wiki.tcl.tk/36776 4522proc hyperlink { name args } { 4523 global fgColor 4524 4525 if {"Underline-Font" ni [font names]} { 4526 font create Underline-Font 4527 } 4528 # font size may have changed 4529 font configure Underline-Font {*}[font actual FixedFontP] -underline true 4530 4531 if { [ dict exists $args -command ] } { 4532 set command [ dict get $args -command ] 4533 dict unset args -command 4534 } 4535 4536 # add -foreground, -font and -cursor, but only if they are missing 4537 set args [ dict merge [ dict create -foreground $fgColor \ 4538 -font Underline-Font -cursor hand2 ] $args ] 4539 4540 ttk::label $name {*}$args 4541 4542 if { [ info exists command ] } { 4543 bind $name <Button-1> $command 4544 } 4545 4546 return $name 4547} 4548 4549proc setBrowser {} { 4550 global command browser 4551 4552 # open is the OS X equivalent to xdg-open on Linux, start is used on Windows 4553 set commands {xdg-open open start} 4554 foreach browser $commands { 4555 if {$browser eq "start"} { 4556 set command [list {*}[auto_execok start] {}] 4557 } else { 4558 set command [auto_execok $browser] 4559 } 4560 if {[string length $command]} { 4561 break 4562 } 4563 } 4564 4565 if {[string length $command] == 0} { 4566 return -code error "couldn't find browser" 4567 } 4568} 4569 4570######################################################################## 4571# MAIN ROUTINE STARTS HERE # 4572######################################################################## 4573 4574if {$nameWidth == "" 4575 || ![regexp {^[2345]+[0-9]+$} $nameWidth] 4576 || $nameWidth > 50} { 4577 exitMsg 10 "nameWidth should be 20-50 but is \"$nameWidth\"" 4578} 4579 4580if {$ClipboardPopup == 1} { 4581 if {$ClipboardPopupTime == "" || ![regexp {^\d$} $ClipboardPopupTime]} { 4582 exitMsg 10 "ClipboardPopupTime should be 0-9 but is \"$ClipboardPopupTime\"" 4583 } 4584} elseif {$ClipboardPopup != 0} { 4585 exitMsg 10 "ClipboardPopup should be 0-1 but is \"$ClipboardPopup\"" 4586} 4587 4588# AndroWish - packages sdltk and borg are included, no need to install 4589set sdltk_present [expr {[info commands "sdltk"]} ne {""}] 4590set borg_present [expr {[info commands "borg"]} ne {""}] 4591 4592if {$NoGUI} { 4593 if {$Host == ""} {set Host $DefaultHost} 4594 if {$Port == ""} {set Port $DefaultPort} 4595} else { 4596 switch $::tcl_platform(platform) { 4597 "unix" { 4598 set rcfile $UnixRCfile 4599 set asfile $UnixASfile 4600 } 4601 "windows" { 4602 #set rcfile [file join $::env(AppData) "ncid.dat"] 4603 set rcfile $WinRCfile 4604 } 4605 } 4606 if {$PortableDir != ""} {set rcfile [file join $PortableDir ".ncid"]} 4607 4608 processRCfile 4609 set delayedMsgs "$delayedMsgs\nProcessed RC file: $rcfile" 4610 set RCfileHost $Host 4611 set RCfilePort $Port 4612 set RCfileoldHost $oldHost 4613 set RCfileoldPort $oldPort 4614 set RCfileHosts $Hosts 4615 set RCfileHostIndex $HostIndex 4616 set RCfileThemeName $ThemeName 4617} 4618 4619getArg 4620set delayedMsgs "$delayedMsgs\nProcessed command line arguments" 4621 4622checkHosts 4623 4624if {![regexp {^[0-2]+$} $LogEnable]} { 4625 set LogStatus "Log enable out of range: $LogEnable" 4626 set LogEnable 0 4627} 4628 4629if {$LogEnable > 0} { 4630 # Make sure LogDir is created or set LogEnable 0 4631 if {$PortableDir != ""} {set LogDir [file join $PortableDir "logs"]} 4632 if {[regexp {[/+\w+]$} $LogDir]} { 4633 if {![file isdirectory $LogDir]} { 4634 if {[catch {file mkdir $LogDir} msg]} { 4635 set LogEnable 0; set LogStatus $msg 4636 } 4637 } 4638 set LogDirLocation "Log Directory: [file normalize $LogDir]" 4639 } else {set LogEnable 0} 4640 if {$LogEnable > 0} {doLogOpen} 4641} 4642 4643set oldHost $Host 4644set oldPort $Port 4645set ArgHost $Host 4646set ArgPort $Port 4647set ArgoldHost $oldHost 4648set ArgoldPort $oldPort 4649set ArgHosts $Hosts 4650set ArgHostIndex $HostIndex 4651 4652if {$NoGUI && $Verbose == 0} {set Verbose 1} 4653 4654if {$HostnameFlag} { 4655 regsub {ncid} $VersionIDENT "$hostname/ncid" VersionIDENT 4656} else { 4657 set LineName ncid 4658} 4659 4660if {$Module != ""} { 4661 regsub {.*/(.*)} $Module {\1} ModName 4662 if {$NoGUI} { 4663 regsub {ncid} $VersionInfo "$ModName" VersionInfo 4664 regsub {ncid} $VersionIDENT "$ModName" VersionIDENT 4665 } else { 4666 regsub {ncid} $VersionInfo "ncid using module $ModName" VersionInfo 4667 regsub {ncid} $VersionIDENT "ncid using module $ModName" VersionIDENT 4668 } 4669} 4670 4671# LoginName on chromebook and android are system-generated user names 4672# like uX_aYY where X is a user# like 0, 1, 2 and YY seems to be a 4673# process id for that user instance. It's currently not possible to 4674# retrieve the gmail address associated with the login user. 4675if {[machine platform] == "chromebook" } { 4676 set LoginName "chromebook user" 4677} elseif {[machine platform] == "android" } { 4678 set LoginName "android user" 4679} else { 4680 set LoginName $tcl_platform(user) 4681} 4682 4683# log command line and any options on separate lines 4684 set cl "Command line: $::argv0" 4685 for {set cnt 0} {$cnt < $::argc} {incr cnt} { 4686 set optarg [lindex $::argv [expr $cnt + 1]] 4687 set opt [lindex $::argv $cnt] 4688 if {[string index $opt 0] == "-"} { 4689 logMsg $::LEVEL1 $cl 4690 set cl " $opt" 4691 } else { 4692 append cl " " $opt; 4693 } 4694 } 4695 logMsg $::LEVEL1 $cl 4696 4697logMsg $::LEVEL1 "$VersionInfo" 4698if {$NoGUI} { 4699 logMsg $::LEVEL1 " Command line mode" 4700} else { 4701 logMsg $::LEVEL1 " GUI mode" 4702} 4703logMsg $::LEVEL1 "Verbose Level: $Verbose" 4704 4705# bug in AndroWish - as of version 2018-06-30, 4706# '[info nameofexecutable]' returns null 4707if {($Interpreter == "") && ([machine platform] == "android")} { 4708 set Interpreter $::env(PACKAGE_CODE_PATH)/wish 4709} 4710logMsg $::LEVEL1 "Interpreter: $Interpreter" 4711logMsg $::LEVEL1 "Default Host: $DefaultHost" 4712logMsg $::LEVEL1 "Default Port: $DefaultPort" 4713if {!$NoGUI && $::tcl_platform(platform) == "unix"} { 4714 logMsg $::LEVEL1 "AutoStart File: $asfile" 4715} 4716 4717# Observed OS encoding systems 4718# Windows 10: cp1252 4719# Mac (native GUI): utf-8 4720# Mac (XQuartz): utf-8 4721# AndroWish: utf-8 4722# Linux: utf-8 4723 4724logMsg $::LEVEL1 "Operating System Encoding: [encoding system]" 4725 4726if {$LogDirLocation != ""} {logMsg $::LEVEL1 $LogDirLocation} 4727logMsg $::LEVEL1 $LogStatus 4728logMsg $::LEVEL1 "Platform: [machine platform]" 4729logMsg $::LEVEL1 "OS: [machine os]" 4730if {[machine platform] == "android"} { 4731 logMsg $::LEVEL1 "Android device model: [machine model]" 4732} 4733logMsg $::LEVEL1 "TCL library: [info library]" 4734logMsg $::LEVEL1 "TCL version: [info patchlevel]" 4735 4736if {$PortableDir != ""} { 4737 logMsg $::LEVEL1 "Using PortableDir: $PortableDir" 4738} 4739logMsg $::LEVEL1 $delayedMsgs 4740 4741if {$OptPmsg != ""} {logMsg $::LEVEL1 "$OptPmsg"} 4742 4743if {!$NoGUI} { 4744 set DistThemes [lsort -dictionary [ttk::themes]] 4745 4746 # only allow default theme for now 4747 set DistThemes default 4748 4749 set AddonThemes "" 4750 if {[file isdirectory $ThemeDir] && [glob -nocomplain -dir $ThemeDir *] != 0} { 4751 lappend auto_path $ThemeDir 4752 4753 # This forces an update of the available packages list. 4754 # It's required for package names to find the themes in 4755 # <path>/themes/*.tcl 4756 eval [package unknown] Tcl [package provide Tcl] 4757 set AddonThemes [lsort -dictionary [ttk::themes]] 4758 foreach t $DistThemes { 4759 set AddonThemes [lsearch -all -inline -not -exact $AddonThemes "$t"] 4760 } 4761 } 4762 4763 #on Windows, force dialogs to have readable checkboxes and radiobuttons 4764 #test by going to View->TYPEs->Select and Preferences->Date and Time 4765 #acceptable : alt default classic 4766 #unacceptable: winnative clam vista 4767 if {[machine platform] == "windows"} {ttk::style theme use "default"} 4768 4769 #on AndroWish, any style besides droid is acceptable 4770 if {[ttk::style theme use] == "droid"} {ttk::style theme use "default"} 4771 4772} 4773 4774logMsg $::LEVEL1 "HostnameFlag: $HostnameFlag" 4775logMsg $::LEVEL1 "LineName: $LineName" 4776logMsg $::LEVEL1 "LoginName: $LoginName" 4777logMsg $::LEVEL1 "Delay between reconnect tries to the server: $Delay (seconds)" 4778 4779# dump environment variables - useful when running in portable mode 4780logArray $::LEVEL5 "Environment variables:" ::env 4781 4782set About \ 4783" 4784$VersionInfo 4785$Author 4786" 4787 4788if {!$NoGUI} { 4789 logMsg $::LEVEL1 "Detected windowing system: [machine osgui]" 4790 logMsg $::LEVEL1 "Distributed Themes: $DistThemes" 4791 logMsg $::LEVEL1 "Custom Themes: day night" 4792 if {$AddonThemes != ""} { 4793 logMsg $::LEVEL1 "Addon Themes Dir: $ThemeDir" 4794 logMsg $::LEVEL1 "Addon Themes: $AddonThemes" 4795 } 4796 logMsg $::LEVEL1 "Current Theme: $ThemeName" 4797 logMsg $::LEVEL1 "ImageDir: $ImageDir" 4798 logMsg $::LEVEL1 "Popup time: $PopupTime" 4799 if {$NoExit} { 4800 set ExitOn do_nothing 4801 logMsg $::LEVEL1 "The \"Close Window\" ttk::button is disabled" 4802 } 4803 if {![regexp {^(:?char|word|none)$} $WrapLines]} { 4804 logMsg $::LEVEL1 "WrapLines set to invalid value of \"$WrapLines\", using default" 4805 set WrapLines "char" 4806 } else { 4807 logMsg $::LEVEL1 "WrapLines set to \"$WrapLines\"" 4808 } 4809 if {$DialPrefix != ""} { 4810 logMsg $::LEVEL1 "Dial prefix: $DialPrefix" 4811 } else { 4812 logMsg $::LEVEL1 "Dial prefix: none" 4813 } 4814 setBrowser 4815 makeWindow 4816 4817 logMsg $::LEVEL1 "Time Field Width: $timeWidth characters" 4818 logMsg $::LEVEL1 "Number Field Width: $nmbrWidth characters" 4819 logMsg $::LEVEL1 "Name Field Width: $nameWidth characters" 4820 logMsg $::LEVEL1 "Line Label Field Width: $lineIDWidth characters" 4821 logMsg $::LEVEL1 "Mesg Type Field Width: $mtypeWidth characters" 4822 logMsg $::LEVEL1 "Calculated History Text Field Width: $historyTextWidth characters" 4823 4824 if {$ClipboardPopup == 0} { 4825 set cpt "$ClipboardPopupTime second" 4826 if {$ClipboardPopupTime != 1} {append cpt "s"} 4827 logMsg $::LEVEL2 "Clipboard Window Popup Time: $cpt" 4828 } else {logMsg $::LEVEL2 "Clipboard Popup Window Time: forever"} 4829 4830 switch $TypeGroups { 4831 0 {logMsg $::LEVEL1 "View Types: All"} 4832 1 {logMsg $::LEVEL1 "View Types: Calls"} 4833 2 {logMsg $::LEVEL1 "View Types: Messages"} 4834 3 {logMsg $::LEVEL1 "View Types: Smart Phone"} 4835 4 {logMsg $::LEVEL1 "View Types: Custom" 4836 logMsg $::LEVEL3 " SelectedTypes contains $SelectedTypes" 4837 } 4838 } 4839 switch $LineIDGroups { 4840 0 {logMsg $::LEVEL1 "View Lines: All"} 4841 >=1 {logMsg $::LEVEL1 "View Lines: $SelectedLineIDs"} 4842 } 4843} 4844 4845checkCountry $Country 4846logMsg $::LEVEL1 "Country Code: $Country" 4847if {$Country == "US"} { 4848 if $NoOne { 4849 logMsg $::LEVEL1 "Leading digit '1' in phone number will NOT be displayed" 4850 } else { 4851 logMsg $::LEVEL1 "Leading digit '1' in phone number WILL be displayed" 4852 } 4853} 4854 4855if {$DateSepar != "/" && $DateSepar != "-" && $DateSepar != "."} { 4856 exitMsg 7 "Date separator \"$DateSepar\" is not supported. Please change it." 4857} 4858 4859if $AltDate { 4860 logMsg $::LEVEL1 "Date Format: DD${DateSepar}MM${DateSepar}YYYY" 4861} else { logMsg $::LEVEL1 "Date Format: MM${DateSepar}DD${DateSepar}YYYY" } 4862 4863if {$WakeUp} { 4864 if {![file executable $ModDir/ncid-wakeup]} { 4865 set WakeUp 0 4866 logMsg $::LEVEL1 "Module ncid-wakeup not found or not executable, wakeup option removed" 4867 } 4868} 4869 4870if {$Module != ""} { 4871 if {[file exists $Module]} { 4872 if {![file executable $Module]} { 4873 # Simple test to see if running under Cygwin 4874 if {[file exists $CygwinBat]} { 4875 # The Cygwin TCL cannot execute shell scripts 4876 set ExecSh 1 4877 } else { 4878 exitMsg 2 "Module Not Executable: $Module" 4879 } 4880 } 4881 } else {exitMsg 3 "Module Not Found: $Module"} 4882 logMsg $::LEVEL1 "Using output Module: $Module" 4883 # change module name from <path>/ncid-<name> to ncid_<name> 4884 regsub {.*/(.*)} $Module {\1} ModName 4885 regsub {\-} $ModName {_} modopt 4886 # set the module option variable in $$modopt 4887 if {[catch {eval [subst $$modopt]} oops]} { 4888 logMsg $::LEVEL1 "No optional \"$modopt\" variable in ncid.conf" 4889 } else { 4890 regsub {.*set *(\w+)\s+.*} [eval concat $$modopt] {\1} modvar 4891 regsub {.*set *(\w+)\s+(\w+).*} [eval concat $$modopt] {\2} modval 4892 if {$modvar == "Ring"} { set CallOnRing 1 } 4893 logMsg $::LEVEL1 "Optional \"$modopt\" variable set \"$modvar\" to \"$modval\" in ncid.conf" 4894 } 4895 if {$CallOnRing} { 4896 switch -- $Ring { 4897 -9 {logMsg $::LEVEL1 "Will execute $Module every ring after CID"} 4898 -2 {logMsg $::LEVEL1 "Will execute $Module after hangup after answer"} 4899 -1 {logMsg $::LEVEL1 "Will execute $Module after hangup with no answer"} 4900 0 {logMsg $::LEVEL1 "Will execute $Module when ringing stops"} 4901 default {logMsg $::LEVEL1 "Will execute $Module at Ring $Ring"} 4902 } 4903 } elseif {$Module != ""} { 4904 logMsg $::LEVEL1 "Will execute $Module when CID arrives" 4905 } 4906} 4907 4908# dump certain variables for troubleshooting 4909 logMsg $::LEVEL5 "" 4910 logMsg $::LEVEL5 "Status of variables after processing the config file:" 4911 logMsg $::LEVEL5 " Host: $ConfigFileHost" 4912 logMsg $::LEVEL5 " Port: $ConfigFilePort" 4913 logMsg $::LEVEL5 " oldHost: $ConfigFileoldHost" 4914 logMsg $::LEVEL5 " oldPort: $ConfigFileoldPort" 4915 logMsg $::LEVEL5 " Hosts: $ConfigFileHosts" 4916 logMsg $::LEVEL5 " HostIndex: $ConfigFileHostIndex" 4917 4918 if {!$NoGUI} { 4919 logMsg $::LEVEL5 "" 4920 logMsg $::LEVEL5 "Status of variables after processing RC file:" 4921 logMsg $::LEVEL5 " Host: $RCfileHost" 4922 logMsg $::LEVEL5 " Port: $RCfilePort" 4923 logMsg $::LEVEL5 " oldHost: $RCfileoldHost" 4924 logMsg $::LEVEL5 " oldPort: $RCfileoldPort" 4925 logMsg $::LEVEL5 " Hosts: $RCfileHosts" 4926 logMsg $::LEVEL5 " HostIndex: $RCfileHostIndex" 4927 logMsg $::LEVEL5 " ThemeName: $RCfileThemeName" 4928 } 4929 4930 logMsg $::LEVEL5 "" 4931 logMsg $::LEVEL5 "Status of variables after processing command line arguments:" 4932 logMsg $::LEVEL5 " Host: $ArgHost" 4933 logMsg $::LEVEL5 " Port: $ArgPort" 4934 logMsg $::LEVEL5 " oldHost: $ArgoldHost" 4935 logMsg $::LEVEL5 " oldPort: $ArgoldPort" 4936 logMsg $::LEVEL5 " Hosts: $ArgHosts" 4937 logMsg $::LEVEL5 " HostIndex: $ArgHostIndex" 4938 logMsg $::LEVEL5 "" 4939 4940if {$NoGUI} doPID 4941connectCID 4942if {!$NoGUI} {bind .im <KeyPress-Return> handleGUIMSG} 4943 4944# enter event loop 4945vwait forever 4946