home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1999 March B
/
SCO_CASTOR4RRT.iso
/
scoadmin
/
root.3
/
etc
/
mail
/
admin
/
domain
/
domain~
Wrap
Text File
|
1998-08-19
|
78KB
|
2,514 lines
#!/bin/osavtcl
#******************************************************************************
#
# Copyright (C) 1993-1997 The Santa Cruz Operation, Inc.
# All Rights Reserved.
#
# The information in this file is provided for the exclusive use of
# the licensees of The Santa Cruz Operation, Inc. Such users have the
# right to use, modify, and incorporate this code into other products
# for purposes authorized by the license agreement provided they include
# this notice and the associated copyright notice with any such product.
# The information in this file is provided "AS IS" without warranty.
#
#===============================================================================
loadlibindex /usr/lib/sysadm.tlib
proc SCO_MAIL_ADMIN_DOMAIN_MSGS {} {}
global SCO_MAIL_ADMIN_DOMAIN_MSGS
set SCO_MAIL_ADMIN_DOMAIN_MSGS(@catalog@) {domain.cat@mail 1}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_HELPBOOK) {1 domain}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_TITLE) {2 {Domain Table File %1$s}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ITEMS) {3 Entries}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_FILE_DOESNT_EXIST) {4 {File does not exist}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_OK) {5 OK}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_CANCEL) {6 Cancel}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_HELP) {7 Help}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_COLUMN_PARTIAL_LBL) {8 *}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_COLUMN_PARTIAL_LBL_CHARM) {9 x}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_COLUMN_PARTIAL_NONE) {10 { }}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_COLUMN_HOST_LBL) {11 Host}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_COLUMN_ROUTE_LBL) {12 {Route Via}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_OBJECT) {13 Entry}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_OBJECT_MN) {14 E}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_ADD_LBL) {15 Add...}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_ADD_MN) {16 A}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_ADD_SH) {17 {Add a domain table entry...}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_DELETE_LBL) {18 Delete}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_DELETE_MN) {19 D}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_DELETE_SH) {20 {Delete a domain table entry}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_MODIFY_LBL) {21 Modify...}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_MODIFY_MN) {22 M}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_MODIFY_SH) {23 {Modify a domain table entry...}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_UP_LBL) {24 {Move Up}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_UP_MN) {25 U}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_UP_SH) {26 {Move a domain table entry up in order}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_DOWN_LBL) {27 {Move Down}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_DOWN_MN) {28 o}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_DOWN_SH) {29 {Move a domain table entry down in order}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_SAVE_LBL) {30 Save}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_SAVE_MN) {31 S}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_SAVE_SH) {32 {Save any changes}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_EXIT_LBL) {33 Exit}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_EXIT_MN) {34 x}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_EXIT_SH) {35 {Exit %s}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_OPTIONS_MENU) {36 Options}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_OPTIONS_MN) {37 O}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_OPTIONS_TOOLBAR) {38 Toolbar}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_OPTIONS_TOOLBAR_SH) {39 {Show/hide Toolbar}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ADD_TITLE) {40 {Add Domain Table Entry}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_MODIFY_TITLE) {41 {Modify Domain Table Entry}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_NAME_LBL) {42 Name}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_NAME_SH) {43 {Enter the host name to be matched for this entry}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_NAME_MISSING) {44 {No host name specified for \"Name\" field}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_REAL_NAME_LBL) {45 {Real Name}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_REAL_NAME_SH) {46 {Enter the real host name mail will be sent to}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_REAL_NAME_MISSING) {47 {No host name specified for \"Real Name\" field}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_NAME_SPACE) {48 {A host name may not contain a space}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_NAME_DUPLICATE) {49 {An entry for host name \"%1$s\" already exists}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_NUMERIC) {50 {Subdomain lookups are not allowed on numeric addresses}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ROUTE_LIST_LBL) {51 {Route to host:}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_ENTER_NAME) {52 {You did not enter a host name}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ROUTE_ADD_BTN_LBL) {53 { Add... }}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ROUTE_ADD_BTN_SH) {54 {Add a host to the route}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ROUTE_DELETE_BTN_LBL) {55 { Delete }}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ROUTE_DELETE_BTN_SH) {56 {Delete a host from the route}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ROUTE_UP_BTN_SH) {57 {Move this host name up in the route}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ROUTE_DOWN_BTN_SH) {58 {Move this host name down in the route}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_DO_PARTIAL_LBL) {59 {Do subdomain lookups}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_DO_PARTIAL_SH) {60 {Allow subdomain lookups on the host name}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ROUTE_ADD_DLG_TITLE) {61 {Add To Route}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ROUTE_ADD_DLG_TEXT_LBL) {62 {Enter host name(s):}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ROUTE_ADD_DLG_BTN_LBL) {63 Select...}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_SAVE_CONFIRM_TITLE) {64 {Save Changes?}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_SAVE_CONFIRM_QUERY) {65 {Do you wish to save the changes made?}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_SAVE_CONFIRM_BTN_YES) {66 Yes}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_SAVE_CONFIRM_BTN_NO) {67 No}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_SAVE_CONFIRM_BTN_CANCEL) {68 Cancel}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_TB_ADD) {69 Add...}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_TB_DELETE) {70 Delete}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_TB_MODIFY) {71 Modify...}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_DL_ARROW_PX) {72 /etc/mail/admin/px/arrow.px}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_DL_CHECK_PX) {73 /etc/mail/admin/px/check.px}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_BTN_UP_PX) {74 /etc/mail/admin/px/prev.px}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_BTN_DOWN_PX) {75 /etc/mail/admin/px/next.px}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_SELECTED) {76 Selected}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_COUNT_LABEL_STR) {77 {%1$s %2$s, %3$s %4$s}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_PARTIAL_LABEL_STR) {78 {* = entry allows subdomain lookups on the host name}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_PARTIAL_LABEL_STR_CHARM) {79 {x = entry allows subdomain lookups on the host name}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_INIT) {80 Initializing...}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_REFRESH) {81 {Loading domain table data...}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_SAVE) {82 {Saving domain table data...}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_USAGE) {83 {Usage: %1$s -f filename [-h hostname]}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_DIRECTORY) {84 {\"%1$s\" is a directory, not a file}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_DATABASE) {85 {Unable to create domain table database\n\"%1$s\"}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_WRITE) {86 {Unable to write domain table file\n\"%1$s\"}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_LOAD) {87 {Unable to load domain table file\n\"%1$s\"}}
set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_NONSTDCMD) {88 %s}
set appvals(intlpre) SCO_MAIL_ADMIN_DOMAIN ;# i10n msg prefix
proc IntlMsg {id {argList {}}} {
global appvals
return [IntlLocalizeMsg $appvals(intlpre)_MSG_$id $argList]
}
proc IntlErr {id {argList {}}} {
global appvals
return [IntlLocalizeMsg $appvals(intlpre)_ERR_$id $argList]
}
proc IntlErrId {id} {
global appvals
return $appvals(intlpre)_ERR_$id
}
proc ConfigFile:Open {} {
global Config_next
if {![info exists Config_next]} {
set Config_next 0
}
set file "config$Config_next"
incr Config_next
upvar #0 Config_${file}_next file_next
set file_next "1.0"
return $file
}
proc ConfigFile:Close {file} {
upvar #0 Config_$file fileList
upvar #0 Config_${file}_next file_next
unset file_next
foreach line [ConfigFile:GetList $file] {
unset fileList($line)
}
}
proc ConfigFile:Compare {line1 line2} {
set subLine1 [ctoken line1 "."]
set subLine2 [ctoken line2 "."]
if {$subLine1 == "" && $subLine2 == ""} {
return 0
} elseif {$subLine1 == ""} {
return -1
} elseif {$subLine2 == ""} {
return 1
} elseif {$subLine1 < $subLine2} {
return -1
} elseif {$subLine1 > $subLine2} {
return 1
} else {
set line1 [string trimleft $line1 "."]
set line2 [string trimleft $line2 "."]
return [ConfigFile:Compare $line1 $line2]
}
}
proc ConfigFile:ReplaceLine {file line type id dataVar} {
upvar #0 Config_$file fileList
upvar #0 Config_${file}_next file_next
upvar $dataVar data
keylset fileList($line) type $type
keylset fileList($line) data $data
keylset fileList($line) id $id
if {[ConfigFile:Compare $line $file_next] == 1} {
set temp $line
set file_next [ctoken temp "."]
incr file_next
set file_next "${file_next}.0"
}
}
proc ConfigFile:AppendLine {file line type id dataVar} {
upvar #0 Config_$file fileList
upvar #0 Config_${file}_next file_next
upvar $dataVar data
if {$line == -1} {
set line $file_next
set temp [ctoken file_next "."]
incr temp
set file_next "${temp}.0"
} else {
set found 0
set left [ctoken line "."]
set right [ctoken line "."]
if {$right == "0"} {
set tryNext $left
incr tryNext
set tryNext "${tryNext}.0"
if {![info exists fileList($tryNext)]} {
set found 1
}
}
if {!$found} {
set lastDigit [cindex $right end]
if {$lastDigit < 9} {
incr lastDigit
set tryNext "${left}.[csubstr $right 0 end]${lastDigit}"
if {![info exists fileList($tryNext)]} {
set found 1
}
}
}
if {!$found} {
set leadingZeros ""
set tryNext "${left}.${right}.1"
while {[info exists fileList($tryNext)]} {
set leadingZeros "${leadingZeros}.0"
set tryNext "${left}.${right}${leadingZeros}.1"
}
}
set line $tryNext
}
keylset fileList($line) type $type
keylset fileList($line) id $id
keylset fileList($line) data $data
if {[string compare $line $file_next] == 1} {
set temp $line
set file_next [ctoken temp "."]
incr file_next
set file_next "${file_next}.0"
}
return $line
}
proc ConfigFile:GetLine {file line typeVar idVar dataVar} {
upvar #0 Config_$file fileList
upvar $typeVar type
upvar $idVar id
upvar $dataVar data
if {![info exists fileList($line)]} {
set type {}
set id {}
set data {}
return -1
}
keylget fileList($line) type type
keylget fileList($line) id id
keylget fileList($line) data data
return 0
}
proc ConfigFile:RemoveLine {file line} {
upvar #0 Config_$file fileList
if {![info exists fileList($line)]} {
# already gone
return
}
unset fileList($line)
}
proc ConfigFile:GetList {file} {
upvar #0 Config_$file fileList
if {![info exists fileList]} {
return {}
}
return [lsort -command ConfigFile:Compare [array names fileList]]
}
proc Table:ProcessLine {fileID type id data} {
global Table_lastType Table_lastID
set lineNum [ConfigFile:AppendLine $fileID -1 $type $id data]
if {[Table:GetOption $fileID makelower] != {}} {
set id [string tolower $id]
}
case $type {
CONTINUATION {
set type $Table_lastType
set id $Table_lastID
}
COMMENT {
}
default {
set Table_lastType $type
set Table_lastID $id
}
}
if {$id != {}} {
upvar #0 Table_${fileID}_$type typeList
lappend typeList($id) $lineNum
}
}
proc Table:Read {fileName callBack mode} {
global Table_info
if {[info exists Table_info($fileName.ID)]} {
return $Table_info($fileName.ID)
}
set fileID [ConfigFile:Open]
set Table_info($fileID.mode) $mode
if {![file exists $fileName]} {
return $fileID
}
set fp [open $fileName r]
set Table_info($fileName.ID) $fileID
set Table_info($fileID.fileName) $fileName
eval $callBack $fileID $fp
close $fp
return $fileID
}
proc Table:Write {fileID {fileName {}} {callBack {}}} {
global Table_info
if {[info exists Table_info($fileID.deferred)]} {
return
}
if {![info exists Table_info($fileID.modified)] && $fileName == {}} {
return
}
if {$callBack == {}} {
set callBack $Table_info($fileID.writeCB)
}
if {$fileName == {}} {
set fileName $Table_info($fileID.fileName)
set clearModified 1
} else {
set clearModified 0
}
#
# If the file exists, make sure the new file has the
# same owner and perms. Otherwise, make sure the
# parent directory exists.
#
if {[file exists $fileName]} {
file stat $fileName info
set Table_info($fileID.uid) $info(uid)
set Table_info($fileID.gid) $info(gid)
set Table_info($fileID.mode) $info(mode)
} else {
set directory [file dirname $fileName]
set oldUmask [umask]
umask 0222
if {![file isdirectory $directory]} {
mkdir -path $directory
}
umask $oldUmask
}
set fp [open ${fileName}.new w]
chmod $Table_info($fileID.mode) ${fileName}.new
if {[info exists Table_info($fileID.uid)]} {
chown [list $Table_info($fileID.uid) $Table_info($fileID.gid)] \
${fileName}.new
}
foreach line [ConfigFile:GetList $fileID] {
if {[ConfigFile:GetLine $fileID $line type id data] != 0} {
continue
}
eval "$callBack $fileID $fp {$type} {$id} {$data}"
}
close $fp
if {[file exists $fileName]} {
unlink $fileName
}
frename ${fileName}.new $fileName
if {$clearModified} {
unset Table_info($fileID.modified)
}
}
proc Table:Open {fileName readCB writeCB {mode 0666}} {
global Table_info
set fileID [Table:Read $fileName $readCB $mode]
set Table_info($fileID.fileName) $fileName
set Table_info($fileID.readCB) $readCB
set Table_info($fileID.writeCB) $writeCB
set Table_info($fileName.ID) $fileID
return $fileID
}
proc Table:Close {fileID {fileName {}}} {
global Table_info
if {![info exists Table_info($fileID.fileName)]} {
return
}
if {[info exists Table_info($fileID.deferred)]} {
unset Table_info($fileID.deferred)
}
Table:Write $fileID $fileName $Table_info($fileID.writeCB)
if {$fileName == {}} {
set fileName $Table_info($fileID.fileName)
}
unset Table_info($fileID.fileName)
unset Table_info($fileName.ID)
ConfigFile:Close $fileID
}
proc Table:CloseNoWrite {fileID {fileName {}}} {
global Table_info
if {![info exists Table_info($fileID.fileName)]} {
return
}
if {[info exists Table_info($fileID.deferred)]} {
unset Table_info($fileID.deferred)
}
if {$fileName == {}} {
set fileName $Table_info($fileID.fileName)
}
unset Table_info($fileID.fileName)
unset Table_info($fileName.ID)
ConfigFile:Close $fileID
}
proc Table:DeferWrites {fileID} {
global Table_info
set Table_info($fileID.deferred) 1
}
proc Table:ForceWrites {fileID} {
global Table_info
if {[info exists Table_info($fileID.deferred)]} {
unset Table_info($fileID.deferred)
}
set Table_info($fileID.modified) 1
}
proc Table:SetOption {fileID option {value 1}} {
global Table_options
set Table_options($fileID.$option) $value
}
proc Table:HasOption {fileID option} {
return [info exists Table_options($fileID.$option)]
}
proc Table:GetOption {fileID option} {
global Table_options
if {![info exists Table_options($fileID.$option)]} {
return {}
}
return $Table_options($fileID.$option)
}
proc Table:Modified {fileID} {
global Table_info
if {[info exists Table_info($fileID.modified)]} {
return $Table_info($fileID.modified)
} else {
return 0
}
}
proc Table:GetLineList {fileID type {idList {}}} {
upvar #0 Table_${fileID}_$type typeList
if {![info exists typeList]} {
return {}
}
if {$idList == {}} {
set idList [array names typeList]
}
set lineList {}
foreach id $idList {
if {[info exists typeList($id)]} {
append lineList " $typeList($id)"
}
}
return [lsort -command ConfigFile:Compare $lineList]
}
proc Table:Get {fileID type id {separator {}}} {
upvar #0 Table_${fileID}_$type typeList
if {[Table:GetOption $fileID makelower] != {}} {
set id [string tolower $id]
}
set value {}
if {![info exists typeList($id)]} {
return $value
}
set numLines [llength [Table:GetLineList $fileID $type $id]]
set thisLine 1
foreach line $typeList($id) {
ConfigFile:GetLine $fileID $line dummy dummy data
if {$thisLine == $numLines} {
append value "$data"
} else {
set data [string trim $data "$separator"]
append value "$data$separator"
}
incr thisLine
}
set value [string trimleft $value $separator]
return $value
}
proc Table:Set {fileID type id data} {
upvar #0 Table_${fileID}_${type} typeList
global Table_info
global Table_lastType Table_lastID
set name $id
if {[Table:GetOption $fileID makelower] != {}} {
set id [string tolower $id]
}
if {[info exists typeList($id)]} {
foreach line $typeList($id) {
ConfigFile:RemoveLine $fileID $line
}
set line [lindex $typeList($id) 0]
unset typeList($id)
} else {
if {[set lineList [Table:GetLineList $fileID $type]] != {}} {
set line [lindex $lineList end]
} else {
if {[Table:GetOption $fileID newFirst] == 1} {
set line 0
} else {
set line -1
}
}
}
lappend typeList($id) [ConfigFile:AppendLine $fileID $line \
$type $name data]
set Table_lastType $type
set Table_lastID $id
set Table_info($fileID.modified) 1
}
proc Table:Unset {fileID type id} {
upvar #0 Table_${fileID}_$type typeList
global Table_info
if {[Table:GetOption $fileID makelower] != {}} {
set id [string tolower $id]
}
if {![info exists typeList($id)]} {
return
}
foreach line $typeList($id) {
ConfigFile:RemoveLine $fileID $line
}
unset typeList($id)
set Table_info($fileID.modified) 1
}
proc Table:AppendLine {fileID type id value {line {}}} {
global Table_lastType Table_lastID
global Table_info
if {$type == "CONTINUATION"} {
upvar #0 Table_${fileID}_$Table_lastType typeList
} else {
upvar #0 Table_${fileID}_$type typeList
}
if {[Table:GetOption $fileID makelower] != {}} {
set id [string tolower $id]
}
if {$line == ""} {
if {[info exists typeList($id)]} {
set line [lindex $typeList($id) end]
} else {
if {[set lineList [Table:GetLineList $fileID $type]] == {}} {
set line [lindex $lineList end]
} else {
if {[Table:GetOption $fileID newFirst] == 1} {
set line 0
} else {
set line -1
}
}
}
}
if {$type == "CONTINUATION"} {
lappend typeList($id) \
[ConfigFile:AppendLine $fileID $line $type {} value]
} else {
lappend typeList($id) \
[ConfigFile:AppendLine $fileID $line $type $id value]
}
set Table_info($fileID.modified) 1
}
proc Table:RemoveLine {fileID type id deleteLine} {
upvar #0 Table_${fileID}_$type typeList
global Table_info
if {[Table:GetOption $fileID makelower] != {}} {
set id [string tolower $id]
}
if {![info exists typeList($id)]} {
return
}
set index 0
foreach line $typeList($id) {
if {$line == $deleteLine} {
lvarpop typeList($id) $index
ConfigFile:RemoveLine $fileID $line
break
}
incr index
}
set Table_info($fileID.modified) 1
}
proc Table:ReplaceLine {fileID type replaceLine id data} {
global Table_info
upvar #0 Table_${fileID}_$type typeList
if {[ConfigFile:GetLine $fileID $replaceLine oldType oldId oldData] == 0} {
if {$oldId != ""} {
upvar #0 Table_${fileID}_$oldType oldTypeList
set index [lsearch -exact $oldTypeList($oldId) $replaceLine]
if {$index != -1} {
lvarpop oldTypeList($oldId) $index
if {[lempty $oldTypeList($oldId)]} {
unset oldTypeList($oldId)
}
}
}
}
ConfigFile:ReplaceLine $fileID $replaceLine $type $id data
if {$id != ""} {
if {![info exists typeList($id)]} {
set typeList($id) {}
}
lappend typeList($id) $replaceLine
}
set Table_info($fileID.modified) 1
}
proc Table:List {fileID type {ordered 0}} {
upvar #0 Table_${fileID}_$type typeList
if {![info exists typeList]} {
return {}
}
if {[Table:GetOption $fileID makelower] == {} && $ordered == 0} {
return [array names typeList]
}
#
# We have to go get the original ids from before they were converted
# to lower case, or they want the ids in the order they appear anyway.
#
set returnList {}
foreach line [Table:GetLineList $fileID $type] {
ConfigFile:GetLine $fileID $line dummy id dummy
append returnList " $id"
}
return [string trimleft $returnList]
}
proc Map:ReadCB {fileID fp} {
set context [scancontext create]
scanmatch $context {^([^#][^ ]*)([ ].*)} {
Table:ProcessLine $fileID entry $matchInfo(submatch0) \
$matchInfo(submatch1)
}
scanmatch $context {
Table:ProcessLine $fileID COMMENT {} $matchInfo(line)
}
scanfile $context $fp
scancontext delete $context
}
proc Map:WriteCB {fileID fp type id data} {
case $type {
entry {
puts $fp "${id}${data}"
}
COMMENT {
puts $fp $data
}
}
}
proc Map:Open {fileName {mode 0644}} {
return [Table:Open $fileName Map:ReadCB Map:WriteCB $mode]
}
proc Map:Write {fileID {fileName {}}} {
return [Table:Write $fileID $fileName]
}
proc Map:ForceWrites {fileID} {
return [Table:ForceWrites $fileID]
}
proc Map:Get {fileID id} {
return [string trimleft [Table:Get $fileID entry $id]]
}
proc Map:Set {fileID id data} {
if {![string match {[ ]*} $data]} {
set data " $data"
}
return [Table:Set $fileID entry $id $data]
}
proc Map:Unset {fileID id} {
return [Table:Unset $fileID entry $id]
}
proc Map:List {fileID} {
set lineOrdered 1
return [Table:List $fileID entry $lineOrdered]
}
proc Map:Insert {fileID id data idBefore} {
if {![string match {[ ]*} $data]} {
set data " $data"
}
# there should really not be duplicate entry ids (keys),
# but in case a duplicate was hand edited in, we pick the first one
# as it is the only one that counts in the map file
set lineBefore [lindex [Table:GetLineList $fileID entry $idBefore] 0]
# put the new entry after $idBefore
Table:AppendLine $fileID entry $id $data $lineBefore
}
proc Map:Modified {fileID} {
return [Table:Modified $fileID]
}
set appvals(vtApp) {} ;# VtOpen return; generally not used
set appvals(vtMain) {} ;# widget string of main dialog
set appvals(toolbar) 1 ;# toolbar
set appvals(toolbarcust) 0 ;# customizable toolbar
set appvals(fieldAdjustment) 0.90 ;# adjustment for string lengths
# for drawn list in graphical
proc UiDefaultFormSpacingSet {form} {
VtSetValues $form \
-horizontalSpacing 0 \
-verticalSpacing 0 \
-marginWidth 0 \
-marginHeight 0
}
proc UiDisplayErrorStackCB {callback cbs} {
global appvals
set dialog [keylget cbs dialog]
VtDestroyDialog $dialog
SaStatusBarClear [VxGetVar $appvals(vtMain) statusBar]
if {![lempty $callback]} {
eval $callback [list $cbs]
}
}
proc UiDisplayErrorStacks {caller stack {callback ""}} {
global appvals
SaDisplayErrorStacks $appvals(vtMain).$caller [list $stack] HELP \
[list UiDisplayErrorStackCB $callback]
}
proc UiSetAppFocus {} {
global appvals
VtSetFocus [VxGetVar $appvals(vtMain) menuBar]
if {![lempty [UiMainListGetItems]]} {
VtSetFocus [VxGetVar $appvals(vtMain) mainList]
}
}
proc AdjustFieldLength {charLength} {
global appvals
set fieldLength [expr $charLength * $appvals(fieldAdjustment)]
return $fieldLength
}
proc UiMainListSetItems {items} {
global appvals
set mainList [VxGetVar $appvals(vtMain) mainList]
VtDrawnListDeleteItem $mainList -all
set maxLength [VxGetVar $mainList maxLength]
DomainSetMainListLabel $maxLength
set isCharm [VtInfo -charm]
set CHARM_formatList [list \
[list STRING 1 1 1] \
[list STRING $maxLength 1 1]]
set MOTIF_formatList [list \
[list STRING 1 10 10] \
[list STRING [AdjustFieldLength $maxLength] 0 10]]
foreach entry $items {
keylget entry partial partial
keylget entry hostName hostName
keylget entry realName realName
keylget entry route route
# set up the first two columns in this list item--
# these are always there:
# indicator of partial domain matching
# hostname (key of domain table entry)
if {$partial == "TRUE"} {
if {$isCharm} {
set partial [IntlMsg COLUMN_PARTIAL_LBL_CHARM]
} else {
set partial [IntlMsg COLUMN_PARTIAL_LBL]
}
} else {
set partial [IntlMsg COLUMN_PARTIAL_NONE]
}
set fieldList [list $partial $hostName]
if {$isCharm} {
set formatList $CHARM_formatList
} else {
set formatList $MOTIF_formatList
}
# for each hop in the route (except final),
# add the string, then the arrow icon
set routeString ""
foreach hop $route {
append routeString "$hop > "
}
# add on the final hop in route
append routeString "$realName"
lappend fieldList $routeString
lappend formatList [list \
STRING \
[AdjustFieldLength [clength $routeString]]]
lappend formatList [list DATA]
lappend fieldList $entry
VtDrawnListAddItem $mainList \
-formatList $formatList \
-fieldList $fieldList
}
}
proc UiMainListGetItems {} {
global appvals
return [VtDrawnListGetItem [VxGetVar $appvals(vtMain) mainList] -all]
}
proc UiMainListCB {cbs} {
global appvals
# update selected label and widget sensitivity
UiUpdateCountLabel
UiSensitizeMainFunctions
}
proc UiMainListDoubleCB {cbs} {
UiModifyEntryCB $cbs
VtUnLock
}
proc UiBuildMainList {form top} {
global appvals
# Build basic main form drawnlist widget including:
# o Manually built title label for CHARM
# o Drawnlist record format
# o traditional Count label beneath the drawn list
set labelFont medNormalFont
set mainList [DomainBuildMainList $form $top]
VxSetVar $form mainList $mainList
set labelForm [VtForm $form.labelForm \
-topSide NONE \
-leftSide FORM \
-rightSide FORM \
-bottomSide FORM]
# Define the partial lookup info label
if {[VtInfo -charm]} {
set label [IntlMsg PARTIAL_LABEL_STR_CHARM]
} else {
set label [IntlMsg PARTIAL_LABEL_STR]
}
set partialLabel [VtLabel $labelForm.partialLabel \
-label $label \
-font smallNormalFont \
-topSide FORM \
-topOffset 0 \
-leftSide FORM \
-MOTIF_leftOffset 5 -CHARM_leftOffset 0 \
-rightSide NONE \
-bottomSide FORM \
-labelLeft]
VxSetVar $form partialLabel $partialLabel
# Define the accompanying count label
set countLabel [VtLabel $labelForm.countLabel -label " " \
-topSide FORM \
-leftSide $partialLabel \
-rightSide FORM \
-bottomSide FORM \
-labelRight]
VxSetVar $form countLabel $countLabel
VtSetValues $mainList -bottomSide $labelForm
# Stash the localized string "Selected" here so we only grab it once
# from the message catalog
VxSetVar $countLabel selected [IntlMsg SELECTED]
# Return the bottom-most widget for further attachments
return $labelForm
}
proc UiUpdateCountLabel {} {
global appvals
set mainList [VxGetVar $appvals(vtMain) mainList]
set countLabel [VxGetVar $appvals(vtMain) countLabel]
set numSelected [llength \
[VtDrawnListGetSelectedItem $mainList -byRecordList]]
lappend labelArgs [llength [VtDrawnListGetItem $mainList -all]]
lappend labelArgs $appvals(itemname)
lappend labelArgs $numSelected
lappend labelArgs [VxGetVar $countLabel selected]
set labelValue [IntlMsg COUNT_LABEL_STR $labelArgs]
VtSetValues $countLabel -label $labelValue
}
proc UiBuildAddModifyScreen {} {
global appvals
set isCharm [VtInfo -charm]
set parent $appvals(vtMain)
set addModifyScreen [VtFormDialog $parent.addModifyScreen \
-ok -okLabel [IntlMsg OK] \
-cancel -cancelLabel [IntlMsg CANCEL] \
-help -helpLabel [IntlMsg HELP] \
-cancelButton CANCEL \
-okCallback AddModifyOkCB \
-cancelCallback AddModifyCancelCB \
-wmCloseCallback AddModifyCancelCB \
-autoLock [list AddModifyOkCB AddModifyCancelCB] \
-resizable FALSE]
VxSetVar $parent addModifyScreen $addModifyScreen
UiDefaultFormSpacingSet $addModifyScreen
SaCharmSetMaxFormDimensions $addModifyScreen 1
set nameForm [VtForm $addModifyScreen.nameForm \
-leftSide FORM -MOTIF_leftOffset 0 -CHARM_leftOffset 1 \
-rightSide FORM -MOTIF_rightOffset 0 -CHARM_rightOffset 1\
-topSide FORM -MOTIF_topOffset 10 -CHARM_topOffset 1]
set nameLabel [VtLabel $nameForm.nameLabel \
-label [IntlMsg NAME_LBL] \
-labelLeft ]
set nameText [VtText $nameForm.nameText \
-leftSide FORM -rightSide FORM \
-shortHelpCallback SaShortHelpCB \
-shortHelpString [IntlMsg NAME_SH] \
-callback {SaSetFocus next}]
VxSetVar $addModifyScreen nameText $nameText
set realNameForm [VtForm $addModifyScreen.realNameForm \
-leftSide FORM -MOTIF_leftOffset 0 -CHARM_leftOffset 1 \
-rightSide FORM -MOTIF_rightOffset 0 -CHARM_rightOffset 1\
-topSide $nameForm -MOTIF_topOffset 0 -CHARM_topOffset 1]
set realNameLabel [VtLabel $realNameForm.realNameLabel \
-label [IntlMsg REAL_NAME_LBL] \
-labelLeft ]
set realNameText [VtText $realNameForm.realNameText \
-leftSide FORM -rightSide FORM \
-shortHelpCallback SaShortHelpCB \
-shortHelpString [IntlMsg REAL_NAME_SH] \
-callback {SaSetFocus next}]
VxSetVar $addModifyScreen realNameText $realNameText
set routeForm [VtForm $addModifyScreen.routeForm \
-leftSide FORM -alignLeft $realNameForm\
-rightSide FORM \
-topSide $realNameForm \
-bottomSide NONE \
-MOTIF_topOffset 10 -CHARM_topOffset 1]
set labelList [list [IntlMsg ROUTE_LIST_LBL]]
if {$isCharm} {
set labelFormat "%s"
set label [format $labelFormat [lindex $labelList 0]]
set routeLabel [VtLabel $routeForm.routeLabel \
-labelLeft \
-leftSide FORM \
-leftOffset 0 \
-rightSide FORM \
-topSide FORM \
-bottomSide NONE \
-label $label]
}
set routeList [VtDrawnList $routeForm.routeList \
-labelFormatList {{STRING 20}} \
-labelList $labelList \
-formatList {{STRING 20}} \
-columns 25 -CHARM_columns 35 \
-rows 6 \
-topSide FORM -bottomSide NONE \
-leftSide FORM -rightSide FORM\
-horizontalScrollBar TRUE \
-selection MULTIPLE \
-callback RouteListCB]
VxSetVar $addModifyScreen routeList $routeList
if {$isCharm} {
VtSetValues $routeList -topSide $routeLabel
}
set buttonForm [VtForm $routeForm.buttonForm \
-leftSide NONE -rightSide FORM \
-MOTIF_rightOffset 0 -CHARM_rightOffset 1 \
-topSide FORM -bottomSide NONE \
-MOTIF_topOffset 15 -CHARM_topOffset 1]
VtSetValues $routeList -rightSide $buttonForm
set pbRowCol1 [VtRowColumn $buttonForm.pbForm1 \
-topSide FORM -bottomSide NONE \
-leftSide FORM -rightSide FORM \
-vertical]
set routeAddButton [VtPushButton $pbRowCol1.routeAddButton \
-label [IntlMsg ROUTE_ADD_BTN_LBL] \
-labelCenter \
-shortHelpCallback SaShortHelpCB \
-shortHelpString \
[IntlMsg ROUTE_ADD_BTN_SH] \
-callback AddToRouteCB \
-autoLock AddToRouteCB ]
VxSetVar $addModifyScreen routeAddButton $routeAddButton
set routeDeleteButton [VtPushButton $pbRowCol1.routeDeleteButton \
-label [IntlMsg ROUTE_DELETE_BTN_LBL] \
-labelCenter \
-shortHelpCallback SaShortHelpCB \
-shortHelpString \
[IntlMsg ROUTE_DELETE_BTN_SH] \
-callback DeleteFromRouteCB \
-autoLock DeleteFromRouteCB ]
VxSetVar $addModifyScreen routeDeleteButton $routeDeleteButton
set pbRowCol2 [VtRowColumn $buttonForm.pbRowCol2 \
-topSide $pbRowCol1 -topOffset 0 -bottomSide NONE \
-leftSide FORM -rightSide FORM \
-horizontal \
-MOTIF_spacing 5 -CHARM_spacing 1 \
-packing COLUMN]
set routeMoveUpButton [VtPushButton $pbRowCol2.routeMoveUpButton \
-shortHelpCallback SaShortHelpCB \
-shortHelpString \
[IntlMsg ROUTE_UP_BTN_SH] \
-callback MoveUpRouteCB \
-autoLock MoveUpRouteCB ]
if {$isCharm} {
VtSetValues $routeMoveUpButton \
-label " [IntlMsg ENTRY_MENU_UP_LBL] " \
-labelCenter
} else {
VtSetValues $routeMoveUpButton \
-pixmap [IntlMsg BTN_UP_PX]
}
VxSetVar $addModifyScreen routeMoveUpButton $routeMoveUpButton
set routeMoveDownButton [VtPushButton $pbRowCol2.routeMoveDownButton \
-shortHelpCallback SaShortHelpCB \
-shortHelpString \
[IntlMsg ROUTE_DOWN_BTN_SH] \
-callback MoveDownRouteCB \
-autoLock MoveDownRouteCB ]
if {$isCharm} {
VtSetValues $routeMoveDownButton \
-label " [IntlMsg ENTRY_MENU_DOWN_LBL] " \
-labelCenter
} else {
VtSetValues $routeMoveDownButton \
-pixmap [IntlMsg BTN_DOWN_PX]
}
VxSetVar $addModifyScreen routeMoveDownButton $routeMoveDownButton
set optionsCheckBox [VtCheckBox $routeForm.optionsCheckBox \
-topSide NONE -bottomSide FORM \
-leftSide FORM -MOTIF_leftOffset 5 -CHARM_leftOffset 0]
set doPartial [VtToggleButton $optionsCheckBox.doPartial \
-label [IntlMsg DO_PARTIAL_LBL] \
-set FALSE \
-shortHelpCallback SaShortHelpCB \
-shortHelpString [IntlMsg DO_PARTIAL_SH] \
-callback {SaSetFocus next}]
VxSetVar $addModifyScreen doPartial $doPartial
set separator [VtSeparator $addModifyScreen.separator \
-leftSide FORM -leftOffset 0 \
-rightSide FORM -rightOffset 0 \
-topSide NONE]
set statusBar [SaStatusBar $addModifyScreen.statusbar 0]
VtSetValues $separator \
-bottomSide $statusBar -bottomOffset 0
VtSetValues $routeList \
-bottomSide $optionsCheckBox
VtSetValues $routeForm \
-bottomSide $separator
SaSetTabGroups $buttonForm [list $pbRowCol1 $pbRowCol2]
SaSetTabGroups $addModifyScreen [list \
$nameText \
$realNameText \
$routeList \
$buttonForm \
$doPartial]
set okButton [VtGetValues $addModifyScreen -ok]
SaSetFocusList $addModifyScreen [list \
$nameText \
$realNameText \
$buttonForm \
$doPartial \
$okButton]
return $addModifyScreen
}
proc UiBuildAddToRouteScreen {parent} {
set addToRouteScreen [VtFormDialog $parent.addToRouteScreen \
-title [IntlMsg ROUTE_ADD_DLG_TITLE] \
-ok -okLabel [IntlMsg OK] \
-okCallback AddToRouteOkCB \
-cancel -cancelLabel [IntlMsg CANCEL] \
-cancelCallback AddToRouteCancelCB \
-cancelButton CANCEL \
-wmCloseCallback AddToRouteCancelCB \
-autoLock [list AddToRouteOkCB AddToRouteCancelCB] ]
VxSetVar $parent addToRouteScreen $addToRouteScreen
set hostNameForm [VtForm $addToRouteScreen.hostNameForm \
-marginHeight 0 -marginWidth 0 \
-rightSide FORM -leftSide FORM \
-topSide FORM -topOffset 10 -CHARM_topOffset 1]
set hostNameLabel [VtLabel $hostNameForm.hostNameLabel \
-label [IntlMsg ROUTE_ADD_DLG_TEXT_LBL] \
-labelLeft ]
set selectHostButton [VtPushButton $hostNameForm.selectHostButton \
-label [IntlMsg ROUTE_ADD_DLG_BTN_LBL] \
-leftSide NONE -rightSide FORM \
-bottomSide FORM -MOTIF_bottomOffset 20 -CHARM_bottomOffset 0 \
-callback SelectHostCB \
-autoLock SelectHostCB]
VxSetVar $addToRouteScreen selectHostButton $selectHostButton
set hostNameText [VtText $hostNameForm.hostNameText \
-columns 30 -CHARM_columns 35 \
-leftSide FORM -rightSide $selectHostButton \
-alignTop $selectHostButton \
-horizontalScrollBar TRUE \
-callback EnterHostNameCB \
-autoLock EnterHostNameCB ]
VxSetVar $addToRouteScreen hostNameText $hostNameText
VtAddTabGroup $hostNameText
VtAddTabGroup $selectHostButton
return $addToRouteScreen
}
proc UiRouteListSetItems {items} {
global appvals
set addModifyScreen [VxGetVar $appvals(vtMain) addModifyScreen]
set routeList [VxGetVar $addModifyScreen routeList]
VtDrawnListDeleteItem $routeList -all
foreach entry $items {
set fieldList [list $entry]
set formatList [list [list STRING [clength $entry]]]
VtDrawnListAddItem $routeList \
-formatList $formatList \
-fieldList $fieldList
}
}
proc UiBuildSaveConfirmDialog {} {
global appvals
set parent $appvals(vtMain)
# we don't do autoDestroy on this dialog, because we
# want wmCloseCallback to do the cancel, and the dialog
# cannot auto destroy in that case
set saveConfirmDlg [VtQuestionDialog $parent.saveConfirmDlg \
-title [IntlMsg SAVE_CONFIRM_TITLE] \
-message [IntlMsg SAVE_CONFIRM_QUERY] \
-autoDestroy FALSE \
-okLabel [IntlMsg SAVE_CONFIRM_BTN_YES] \
-ok -okCallback SaveConfirmOkCB \
-applyLabel [IntlMsg SAVE_CONFIRM_BTN_NO] \
-apply -applyCallback SaveConfirmNoCB \
-cancelLabel [IntlMsg SAVE_CONFIRM_BTN_CANCEL] \
-cancel -cancelCallback SaveConfirmCancelCB \
-wmCloseCallback SaveConfirmCancelCB \
-autoLock [list \
SaveConfirmOkCB SaveConfirmNoCB SaveConfirmCancelCB]]
VxSetVar $parent saveConfirm $saveConfirmDlg
return $saveConfirmDlg
}
proc UiCloseCB {cbs} {
# Call underlying non-ui module: close that may need additional ui
if {[DomainIsModified]} {
CloseWithUi
VtUnLock
return
}
UiStop UiCloseCB2
}
proc UiCloseCB2 {{cbs {}}} {
# Call underlying non-ui module: close without Ui
CloseAfterUi
}
proc UiRefreshCB {{cbs {}}} {
global appvals
set statusBar [VxGetVar $appvals(vtMain) statusBar]
set mainList [VxGetVar $appvals(vtMain) mainList]
SaStatusBarSet $statusBar [IntlMsg REFRESH]
Refresh
# Update count label and widget sensitivity
UiUpdateCountLabel
UiSensitizeMainFunctions
SaStatusBarClear $statusBar
VtUnLock
}
proc EnterHostNameCB {cbs} {
set dialog [keylget cbs dialog]
set widget [keylget cbs widget]
set mode [keylget cbs mode]
set name [keylget cbs value]
if {$mode == "done"} {
if {[lempty $name]} {
VtShow [VtErrorDialog $dialog.usererr1 \
-message [IntlErr ENTER_NAME] \
-ok]
set hostNameText [VxGetVar $dialog hostNameText]
VtSetFocus $hostNameText
VtUnLock
return
} else {
set okButton [VtGetValues $dialog -ok]
VtSetFocus $okButton
}
}
VtUnLock
}
proc SelectHostOkCB {addToRouteScreen cbs} {
global appvals
set dialog [keylget cbs dialog]
set instance $appvals(selecthost)
set selection [SaSelectHostGetSelection $instance]
set hostNameText [VxGetVar $addToRouteScreen hostNameText]
set currentVal [VtGetValues $hostNameText -value]
lappend currentVal $selection
VtSetValues $hostNameText -value $currentVal
VtSetValues $hostNameText \
-xmArgs [list XmNcursorPosition [string length $currentVal]]
VtSetFocus $hostNameText
VtUnLock
}
proc SelectHostCB {cbs} {
global appvals
set parent [keylget cbs dialog]
keylset parameters parent $parent
keylset parameters instance selectHostScreen
set appvals(selecthost) selectHostScreen
keylset parameters userproc "SelectHostOkCB $parent"
SaSelectHostDialog $parameters $cbs
}
proc AddToRouteOkCB {cbs} {
set dialog [keylget cbs dialog]
set hostNameText [VxGetVar $dialog hostNameText]
set route [VtGetValues $hostNameText -value]
if {[lempty $route]} {
VtShow [VtErrorDialog $dialog.usererr1 \
-message [IntlErr ENTER_NAME] \
-ok]
VtSetFocus $hostNameText
VtUnLock
return
}
set addModifyScreen [VxGetVar $dialog parent_dlg]
set routeList [VxGetVar $addModifyScreen routeList]
set currentItems [VtDrawnListGetItem $routeList -all]
set currentSelectedItems [VtDrawnListGetSelectedItem $routeList \
-byPositionList]
VtDestroyDialog $dialog
if {[lempty $currentItems]} {
UiRouteListSetItems $route
VtDrawnListSelectItem $routeList -all
} else {
if {$currentSelectedItems == 0} {
UiRouteListSetItems [concat $currentItems $route]
set pos [llength $currentItems]
set positions {}
foreach hop $route {
incr pos
lappend positions $pos
}
VtDrawnListSelectItem \
$routeList -positionList $positions
} else {
set pos [lindex $currentSelectedItems end]
set firstPositions {}
for {set index 1} {$index <= $pos} {incr index} {
lappend firstPositions $index
}
set lastPositions {}
for {set index [expr $pos + 1]} \
{$index <= [llength $currentItems]} {incr index} {
lappend lastPositions $index
}
set lastNewPosition [expr $pos + [llength $route]]
set newPositions {}
for {set index [expr $pos + 1]} \
{$index <= $lastNewPosition} {incr index} {
lappend newPositions $index
}
set begItems [VtDrawnListGetItem $routeList \
-positionList $firstPositions]
set lastItems [VtDrawnListGetItem $routeList \
-positionList $lastPositions]
UiRouteListSetItems [concat $begItems $route $lastItems]
VtDrawnListSelectItem \
$routeList -positionList $newPositions
}
}
SaDrawnListShowSelectedItem $routeList
UiSensitizeAddModifyFunctions $addModifyScreen
VtUnLock
}
proc AddToRouteCancelCB {cbs} {
set dialog [keylget cbs dialog]
VtDestroyDialog $dialog
VtUnLock
return
}
proc AddToRouteCB {cbs} {
set parent [keylget cbs dialog]
set mode [keylget cbs mode]
set name [keylget cbs value]
set addToRouteScreen [UiBuildAddToRouteScreen $parent]
VxSetVar $addToRouteScreen parent_dlg $parent
set hostNameText [VxGetVar $addToRouteScreen hostNameText]
VtShow $addToRouteScreen
VtSetFocus $hostNameText
VtUnLock
}
proc DeleteFromRouteCB {cbs} {
set dialog [keylget cbs dialog]
set routeList [VxGetVar $dialog routeList]
set selectedPositions [VtDrawnListGetSelectedItem \
$routeList -byPositionList]
set prevTotal [llength [VtDrawnListGetItem $routeList -all]]
VtDrawnListDeleteItem $routeList -positionList $selectedPositions
set numItemsLeft [llength [VtDrawnListGetItem $routeList -all]]
if {$numItemsLeft > 0} {
set first [lindex $selectedPositions 0]
set last [lindex $selectedPositions end]
set numDeleted [llength $selectedPositions]
if {[expr $last - $first + 1] == $numDeleted} {
set contiguous 1
} else {
set contiguous 0
}
if {$last == $prevTotal && $contiguous} {
# select the one above
VtDrawnListSelectItem $routeList \
-position [expr $first - 1]
} else {
# select the item that was after the first deleted
# (same position number as first deleted was)
VtDrawnListSelectItem $routeList -position $first
}
SaDrawnListShowSelectedItem $routeList
}
UiSensitizeAddModifyFunctions $dialog
VtUnLock
}
proc RouteListCB {cbs} {
set dialog [keylget cbs dialog]
UiSensitizeAddModifyFunctions $dialog
}
proc MoveUpRouteCB {cbs} {
set dialog [keylget cbs dialog]
set routeList [VxGetVar $dialog routeList]
set selectedNum [lindex \
[VtDrawnListGetSelectedItem $routeList -byPositionList] 0]
if {$selectedNum == 1} {
VtBeep
VtUnLock
return
}
set selectedItem [VtDrawnListGetItem $routeList -position $selectedNum]
set newPosition [expr $selectedNum - 1]
VtDrawnListDeleteItem $routeList -position $selectedNum
VtDrawnListAddItem $routeList -position $newPosition \
-formatList [list [list STRING 25]] \
-fieldList $selectedItem
VtDrawnListSelectItem $routeList -position $newPosition
SaDrawnListShowSelectedItem $routeList
VtUnLock
return
}
proc MoveDownRouteCB {cbs} {
set dialog [keylget cbs dialog]
set routeList [VxGetVar $dialog routeList]
set selectedNum [lindex \
[VtDrawnListGetSelectedItem $routeList -byPositionList] 0]
set totalNum [llength [VtDrawnListGetItem $routeList -all]]
if {$selectedNum == $totalNum} {
VtBeep
VtUnLock
return
}
set selectedItem [VtDrawnListGetItem $routeList -position $selectedNum]
set newPosition [expr $selectedNum + 1]
VtDrawnListDeleteItem $routeList -position $selectedNum
VtDrawnListAddItem $routeList -position $newPosition \
-formatList [list [list STRING 25]] \
-fieldList [list $selectedItem]
VtDrawnListSelectItem $routeList -position $newPosition
SaDrawnListShowSelectedItem $routeList
VtUnLock
return
}
proc AddModifyCancelCB {cbs} {
set dialog [keylget cbs dialog]
VtDestroyDialog $dialog
VtUnLock
return
}
proc AddModifyOkCB {cbs} {
global appvals
set dialog [keylget cbs dialog]
set function [VxGetVar $dialog function]
set nameText [VxGetVar $dialog nameText]
set realNameText [VxGetVar $dialog realNameText]
set routeList [VxGetVar $dialog routeList]
set doPartial [VxGetVar $dialog doPartial]
# get the values entered into the widgets
set newHostName [string trim [VtGetValues $nameText -value]]
set newRealName [string trim [VtGetValues $realNameText -value]]
set newRoute [VtDrawnListGetItem $routeList -all]
set newPartial [VtGetValues $doPartial -value]
if {[clength $newHostName] == 0 || [ctype space $newHostName]} {
VtShow [VtErrorDialog $dialog.usererr1 \
-message [IntlErr NAME_MISSING] \
-ok]
VtUnLock
VtSetFocus $nameText
return
}
if {[regexp {[ ]} $newHostName]} {
VtShow [VtErrorDialog $dialog.usererr2 \
-message [IntlErr NAME_SPACE] \
-ok]
VtUnLock
VtSetFocus $nameText
return
}
if {[clength $newRealName] == 0 || [ctype space $newRealName]} {
VtShow [VtErrorDialog $dialog.usererr3 \
-message [IntlErr REAL_NAME_MISSING] \
-ok]
VtUnLock
VtSetFocus $realNameText
return
}
if {[regexp {[ ]} $newRealName]} {
VtShow [VtErrorDialog $dialog.usererr4 \
-message [IntlErr NAME_SPACE] \
-ok]
VtUnLock
VtSetFocus $realNameText
return
}
# Don't allow partial lookups on numeric addresses
if {[regexp {\[[0-9\.]+\]} $newHostName] && $newPartial} {
VtShow [VtErrorDialog $dialog.usererr5 \
-message [IntlErr NUMERIC] \
-ok]
VtUnLock
VtSetFocus $doPartial
return
}
# set up the new entry
if {$newPartial} {
set newPartial TRUE
keylset newEntry partial $newPartial
} else {
set newPartial FALSE
keylset newEntry partial $newPartial
}
keylset newEntry hostName $newHostName
keylset newEntry realName $newRealName
keylset newEntry route $newRoute
set mainList [VxGetVar $appvals(vtMain) mainList]
set selected [VtDrawnListGetSelectedItem $mainList -byRecordList]
if {$function == "add"} {
if {[DomainEntryExists $newHostName]} {
VtShow [VtErrorDialog $dialog.usererr5 \
-message [IntlErr NAME_DUPLICATE $newHostName] \
-ok]
VtUnLock
VtSetFocus $nameText
return
}
if {[lempty $selected]} {
# just put the new entry last
set position 0
set before [lindex [VtDrawnListGetItem $mainList \
-position 0] 0]
} else {
# put the new entry after the last selected entry
set selectedNum [lindex [VtDrawnListGetSelectedItem \
$mainList -byPositionList] end]
set position [expr $selectedNum + 1]
set before [lindex $selected end]
}
if {[cequal $before ""]} {
set beforeEntry ""
} else {
set beforeEntry [lindex $before end]
}
# update the data structures
DomainAdd $beforeEntry $newEntry
} else {
set position [lindex [VtDrawnListGetSelectedItem $mainList \
-byPositionList] 0]
set oldEntry [lindex [lindex $selected 0] end]
set oldPartial ""
keylget oldEntry partial oldPartial
set oldHostName ""
keylget oldEntry hostName oldHostName
set oldRealName ""
keylget oldEntry realName oldRealName
set oldRoute ""
keylget oldEntry route oldRoute
if {![cequal [string tolower $newHostName] \
[string tolower $oldHostName]] && \
[DomainEntryExists $newHostName]} {
VtShow [VtErrorDialog $dialog.usererr6 \
-message [IntlErr NAME_DUPLICATE $newHostName] \
-ok]
VtUnLock
VtSetFocus $nameText
return
}
set modified 0
if {$newPartial != $oldPartial || \
$newHostName != $oldHostName || \
$newRealName != $oldRealName || \
$newRoute != $oldRoute} {
DomainModify $oldEntry $newEntry
set modified 1
}
}
VtDestroyDialog $dialog
# update the main drawn list
if {$function == "add" || ($function == "modify" && $modified)} {
set maxLength [VxGetVar $mainList maxLength]
set newLength [clength $newHostName]
if {$newLength < $maxLength} {
set newLength $maxLength
}
# For now, we punt on re-drawing the list if the new
# host length is larger than the known max length --
# this is an expensive operation.
set isCharm [VtInfo -charm]
if {$isCharm} {
set formatList [list \
[list STRING 1 1 1] \
[list STRING $newLength 1 1] ]
} else {
set formatList [list \
[list STRING 1 10 10] \
[list STRING [AdjustFieldLength $newLength] 0 10]]
}
if {$newPartial == "TRUE"} {
if {[VtInfo -charm]} {
set fieldList [list \
[IntlMsg COLUMN_PARTIAL_LBL_CHARM]]
} else {
set fieldList [list \
[IntlMsg COLUMN_PARTIAL_LBL]]
}
} else {
set fieldList \
[list [IntlMsg COLUMN_PARTIAL_NONE]]
}
lappend fieldList $newHostName
set routeString ""
foreach hop $newRoute {
append routeString "$hop > "
}
append routeString $newRealName
lappend fieldList $routeString
lappend formatList [list \
STRING \
[AdjustFieldLength [clength $routeString]]]
lappend fieldList $newEntry
lappend formatList [list DATA]
if {$function == "modify"} {
VtDrawnListDeleteItem $mainList -position $position
}
VtDrawnListAddItem $mainList -formatList $formatList \
-fieldList $fieldList \
-position $position
VtDrawnListSelectItem $mainList -position $position
SaDrawnListShowSelectedItem $mainList
UiSensitizeMainFunctions
if {"$function" == "add"} {
UiUpdateCountLabel
}
}
VtUnLock
return
}
proc UiAddEntryCB {cbs} {
set addScreen [UiBuildAddModifyScreen]
VxSetVar $addScreen function add
set nameText [VxGetVar $addScreen nameText]
set addButton [VxGetVar $addScreen routeAddButton]
set deleteButton [VxGetVar $addScreen routeDeleteButton]
set upButton [VxGetVar $addScreen routeMoveUpButton]
set downButton [VxGetVar $addScreen routeMoveDownButton]
VtSetValues $addScreen -title [IntlMsg ADD_TITLE]
VtSetSensitive $addButton 1
VtSetSensitive $deleteButton 0
VtSetSensitive $upButton 0
VtSetSensitive $downButton 0
VtShow $addScreen
VtSetFocus $nameText
VtUnLock
}
proc UiDeleteEntryCB {cbs} {
global appvals
set list [VxGetVar $appvals(vtMain) mainList]
set selectedPositions [VtDrawnListGetSelectedItem $list -byPositionList]
set prevTotal [llength [VtDrawnListGetItem $list -all]]
set deleteEntries {}
foreach item [VtDrawnListGetSelectedItem $list -byRecordList] {
lappend deleteEntries [lindex $item end]
}
DomainDelete $deleteEntries
VtDrawnListDeleteItem $list -positionList $selectedPositions
set numItemsLeft [llength [VtDrawnListGetItem $list -all]]
if {$numItemsLeft > 0} {
set first [lindex $selectedPositions 0]
set last [lindex $selectedPositions end]
set numDeleted [llength $selectedPositions]
if {[expr $last - $first + 1] == $numDeleted} {
set contiguous 1
} else {
set contiguous 0
}
if {$last == $prevTotal && $contiguous} {
# select the one above
VtDrawnListSelectItem $list -position [expr $first - 1]
} else {
# select the item that was after the first deleted
# (same position number as first deleted was)
VtDrawnListSelectItem $list -position $first
}
SaDrawnListShowSelectedItem $list
}
UiSensitizeMainFunctions
UiUpdateCountLabel
VtUnLock
}
proc UiModifyEntryCB {cbs} {
set dialog [keylget cbs dialog]
set mainList [VxGetVar $dialog mainList]
set selected [lindex \
[VtDrawnListGetSelectedItem $mainList -byItemList] 0]
set modifyScreen [UiBuildAddModifyScreen]
VxSetVar $modifyScreen function modify
set nameText [VxGetVar $modifyScreen nameText]
set realNameText [VxGetVar $modifyScreen realNameText]
set routeList [VxGetVar $modifyScreen routeList]
set doPartial [VxGetVar $modifyScreen doPartial]
set addButton [VxGetVar $modifyScreen routeAddButton]
set deleteButton [VxGetVar $modifyScreen routeDeleteButton]
set upButton [VxGetVar $modifyScreen routeMoveUpButton]
set downButton [VxGetVar $modifyScreen routeMoveDownButton]
set modifyEntry [lindex $selected end]
set partial ""
keylget modifyEntry partial partial
set hostName ""
keylget modifyEntry hostName hostName
set realName ""
keylget modifyEntry realName realName
set route ""
keylget modifyEntry route route
VtSetValues $modifyScreen -title [IntlMsg MODIFY_TITLE]
VtSetValues $doPartial -set $partial
VtSetValues $nameText -value $hostName
VtSetValues $realNameText -value $realName
foreach hop $route {
VtDrawnListAddItem $routeList \
-fieldList [list $hop] \
-formatList [list [list STRING 25]]
}
if {[lempty $route]} {
VtSetSensitive $addButton 1
VtSetSensitive $deleteButton 0
VtSetSensitive $upButton 0
VtSetSensitive $downButton 0
} else {
VtSetSensitive $addButton 1
VtSetSensitive $deleteButton 1
VtSetSensitive $upButton 1
VtSetSensitive $downButton 1
VtDrawnListSelectItem $routeList -position 1
}
VtShow $modifyScreen
VtSetFocus $nameText
VtUnLock
}
proc UiMoveUpEntryCB {cbs} {
global appvals
set list [VxGetVar $appvals(vtMain) mainList]
set selectedNum [lindex \
[VtDrawnListGetSelectedItem $list -byPositionList] 0]
if {$selectedNum == 1} {
VtBeep
VtUnLock
return
}
set selectedItem [lindex \
[VtDrawnListGetItem $list -position $selectedNum] 0]
set newPosition [expr $selectedNum - 1]
set beforeItem [lindex \
[VtDrawnListGetItem $list -position $newPosition] 0]
#
# Update table data structures
#
set entry1 [lindex $beforeItem end]
set entry2 [lindex $selectedItem end]
DomainSwapPosition $entry1 $entry2
#
# Modify main list widget
#
# Delete the item selected in the list
VtDrawnListDeleteItem $list -position $selectedNum
# Add the deleted item back in the new position
set maxLength [VxGetVar $list maxLength]
if {[VtInfo -charm]} {
set formatList [list \
[list STRING 1 1 1] \
[list STRING $maxLength 1 1]]
set icon [list ICON 1 1 1]
} else {
set formatList [list \
[list STRING 1 10 10] \
[list STRING [AdjustFieldLength $maxLength] 0 10]]
set icon [list ICON 1 0 5]
}
lappend formatList [list STRING [clength [lindex $selectedItem 2]]]
VtDrawnListAddItem $list -position $newPosition \
-fieldList $selectedItem \
-formatList $formatList
VtDrawnListSelectItem $list -position $newPosition
SaDrawnListShowSelectedItem $list
VtUnLock
}
proc UiMoveDownEntryCB {cbs} {
global appvals
set list [VxGetVar $appvals(vtMain) mainList]
set selectedNum [lindex \
[VtDrawnListGetSelectedItem $list -byPositionList] 0]
set numItems [llength [VtDrawnListGetItem $list -all]]
if {$selectedNum == $numItems} {
VtBeep
VtUnLock
return
}
set selectedItem [lindex \
[VtDrawnListGetItem $list -position $selectedNum] 0]
set newPosition [expr $selectedNum + 1]
set afterItem [lindex \
[VtDrawnListGetItem $list -position $newPosition] 0]
#
# Update table data structures
#
set entry1 [lindex $selectedItem end]
set entry2 [lindex $afterItem end]
DomainSwapPosition $entry1 $entry2
#
# Modify main list widget
#
# Delete the item selected in the list
VtDrawnListDeleteItem $list -position $selectedNum
# Add the deleted item back in the new position
set maxLength [VxGetVar $list maxLength]
if {[VtInfo -charm]} {
set formatList [list \
[list STRING 1 1 1] \
[list STRING $maxLength 1 1]]
set icon [list ICON 1 1 1]
} else {
set formatList [list \
[list STRING 1 10 10] \
[list STRING [AdjustFieldLength $maxLength] 0 10]]
set icon [list ICON 1 0 5]
}
lappend formatList [list STRING [clength [lindex $selectedItem 2]]]
VtDrawnListAddItem $list -position $newPosition \
-fieldList $selectedItem \
-formatList $formatList
VtDrawnListSelectItem $list -position $newPosition
SaDrawnListShowSelectedItem $list
VtUnLock
}
proc SaveConfirmOkCB {cbs} {
set dialog [keylget cbs dialog]
VtDestroyDialog $dialog
if {[UiSaveCB {}] != 1} {
VtUnLock
return
} else {
VtUnLock
UiStop UiCloseCB2
}
}
proc SaveConfirmNoCB {cbs} {
set dialog [keylget cbs dialog]
VtDestroyDialog $dialog
VtUnLock
UiStop UiCloseCB2
}
proc SaveConfirmCancelCB {cbs} {
set dialog [keylget cbs dialog]
VtDestroyDialog $dialog
VtUnLock
return
}
proc UiSaveCB {cbs} {
global appvals
set statusBar [VxGetVar $appvals(vtMain) statusBar]
SaStatusBarSet $statusBar [IntlMsg SAVE]
if {[ErrorCatch errStack 0 DomainWrite data]} {
VtUnLock
UiDisplayErrorStacks UiSaveCB $errStack
return 0
}
SaStatusBarClear $statusBar
VtUnLock
return 1
}
proc UiSensitizeMainFunctions {} {
# visit all appropriate menu items:
# VxGetVar
# VtSetsensitive
global appvals
set mainList [VxGetVar $appvals(vtMain) mainList]
set item [VtDrawnListGetSelectedItem $mainList]
set selected [llength \
[VtDrawnListGetSelectedItem $mainList -byRecordList]]
set menuBar [VxGetVar $appvals(vtMain) menuBar]
set add [VxGetVar $menuBar add]
set delete [VxGetVar $menuBar delete]
set modify [VxGetVar $menuBar modify]
set moveUp [VxGetVar $menuBar moveUp]
set moveDown [VxGetVar $menuBar moveDown]
set isCharm [VtInfo -charm]
if {!$isCharm} {
set toolBar [VxGetVar $appvals(vtMain) toolBar]
set addTB [VxGetVar $toolBar addTB]
set deleteTB [VxGetVar $toolBar deleteTB]
set modifyTB [VxGetVar $toolBar modifyTB]
set upTB [VxGetVar $toolBar upTB]
set downTB [VxGetVar $toolBar downTB]
}
if {$selected == 0} {
VtSetSensitive $delete 0
VtSetSensitive $modify 0
VtSetSensitive $moveUp 0
VtSetSensitive $moveDown 0
if {!$isCharm} {
VtSetSensitive $deleteTB 0
VtSetSensitive $modifyTB 0
VtSetSensitive $upTB 0
VtSetSensitive $downTB 0
}
} elseif {$selected == 1} {
VtSetSensitive $delete 1
VtSetSensitive $modify 1
VtSetSensitive $moveUp 1
VtSetSensitive $moveDown 1
if {!$isCharm} {
VtSetSensitive $deleteTB 1
VtSetSensitive $modifyTB 1
VtSetSensitive $upTB 1
VtSetSensitive $downTB 1
}
} else {
VtSetSensitive $delete 1
VtSetSensitive $modify 0
VtSetSensitive $moveUp 0
VtSetSensitive $moveDown 0
if {!$isCharm} {
VtSetSensitive $deleteTB 1
VtSetSensitive $modifyTB 0
VtSetSensitive $upTB 0
VtSetSensitive $downTB 0
}
}
}
proc UiSensitizeAddModifyFunctions {addModifyScreen} {
set deleteButton [VxGetVar $addModifyScreen routeDeleteButton]
set upButton [VxGetVar $addModifyScreen routeMoveUpButton]
set downButton [VxGetVar $addModifyScreen routeMoveDownButton]
set routeList [VxGetVar $addModifyScreen routeList]
set selected [llength \
[VtDrawnListGetSelectedItem $routeList -byRecordList]]
if {$selected == 0} {
VtSetSensitive $deleteButton 0
VtSetSensitive $upButton 0
VtSetSensitive $downButton 0
} elseif {$selected == 1} {
VtSetSensitive $deleteButton 1
VtSetSensitive $upButton 1
VtSetSensitive $downButton 1
} else {
VtSetSensitive $deleteButton 1
VtSetSensitive $upButton 0
VtSetSensitive $downButton 0
}
}
proc UiStart {} {
global appvals
# Open/connect to widget server
set vtApp [VtOpen $appvals(client) [IntlMsg HELPBOOK]]
set appvals(vtApp) $vtApp
VtSetAppValues $vtApp \
-errorCallback {SaUnexpectedErrorCB {}}
# Create main dialog
set vtMain [VtFormDialog $vtApp.main \
-title $appvals(title) \
-resizable FALSE \
-wmShadowThickness 0 \
-wmCloseCallback UiCloseCB]
set appvals(vtMain) $vtMain
VxSetVar $appvals(vtMain) vtMain $vtMain
UiDefaultFormSpacingSet $vtMain
SaCharmSetMaxFormDimensions $vtMain
# Build pulldown menus
set menuBar [UiBuildMenus $vtMain]
VxSetVar $appvals(vtMain) menuBar $menuBar
# Build the toolbar
if {! [VtInfo -charm]} {
set toolBar [UiBuildToolBar $vtMain $menuBar]
}
# Basic drawnlist for domain table entries
# Pass main form and widget just above for attachments
if {[VtInfo -charm]} {
set mainList [UiBuildMainList $vtMain $menuBar]
} else {
set mainList [UiBuildMainList $vtMain $toolBar]
}
# Build the status bar with standard SCOadmin status bar pixmap
set statusBar [SaStatusBar $vtMain.statusBar 1]
VxSetVar $appvals(vtMain) statusBar $statusBar
# Connect main screen widget bottom to statusbar
VtSetValues $mainList -bottomSide $statusBar
# Display the main form and lock it
VtShow $vtMain
VtLock
}
proc UiStop {cb} {
global appvals
set vtMain $appvals(vtMain)
set client $appvals(client)
# Store modified preferences
# short help
set cmd [list SaShortHelpStore $client]
if {[ErrorCatch errorStack 0 $cmd dummy] != 0 } {
lappend errorStacks $errorStack
}
# any problems?
if [info exists errorStacks] {
# present error dialog and enter event-driven Ui loop.
# Re-gain procedural control via UiStop2 (part 2) and
# eventuall, the caller's cb
SaDisplayErrorStacks $vtMain.UIStop $errorStacks {} \
[list UiStop2 $cb]
VtUnLock
VtMainLoop
} else {
# stop vtcl
VtUnLock
VtClose
# return control to the caller
eval $cb
}
}
proc UiStop2 {cb {cbs {}}} {
VtUnLock
VtClose
# return control to the caller
eval $cb
}
proc UiBuildMenus {form} {
global appvals
set helpMenuItemList [list \
ON_CONTEXT \
ON_WINDOW \
ON_KEYS \
INDEX \
ON_HELP]
set menuBar [VtMenuBar $form.menuBar \
-helpMenuItemList $helpMenuItemList]
VxSetVar $form menuBar $menuBar
# Main object menu
UiBuildObjectMenu $menuBar
# Options menu
UiBuildOptionsMenu $menuBar
return $menuBar
}
proc UiBuildObjectMenu {parent} {
global appvals
set label $appvals(object)
set mnemonic $appvals(objectmn)
set fileMenu [VtPulldown $parent.fileMenu \
-label $label \
-mnemonic $mnemonic \
]
VxSetVar $parent fileMenu $fileMenu
set add [VtPushButton $fileMenu.add \
-label [IntlMsg ENTRY_MENU_ADD_LBL] \
-mnemonic [IntlMsg ENTRY_MENU_ADD_MN] \
-shortHelpCallback SaShortHelpCB \
-shortHelpString [IntlMsg ENTRY_MENU_ADD_SH] \
-callback UiAddEntryCB \
-autoLock UiAddEntryCB]
VxSetVar $parent add $add
set delete [VtPushButton $fileMenu.delete \
-label [IntlMsg ENTRY_MENU_DELETE_LBL] \
-mnemonic [IntlMsg ENTRY_MENU_DELETE_MN] \
-shortHelpCallback SaShortHelpCB \
-shortHelpString [IntlMsg ENTRY_MENU_DELETE_SH] \
-callback UiDeleteEntryCB \
-autoLock UiDeleteEntryCB]
VxSetVar $parent delete $delete
set modify [VtPushButton $fileMenu.modify \
-label [IntlMsg ENTRY_MENU_MODIFY_LBL] \
-mnemonic [IntlMsg ENTRY_MENU_MODIFY_MN] \
-shortHelpCallback SaShortHelpCB \
-shortHelpString [IntlMsg ENTRY_MENU_MODIFY_SH] \
-callback UiModifyEntryCB \
-autoLock UiModifyEntryCB]
VxSetVar $parent modify $modify
VtSeparator $fileMenu.s1
set moveUp [VtPushButton $fileMenu.moveUp \
-label [IntlMsg ENTRY_MENU_UP_LBL] \
-mnemonic [IntlMsg ENTRY_MENU_UP_MN] \
-shortHelpCallback SaShortHelpCB \
-shortHelpString [IntlMsg ENTRY_MENU_UP_SH] \
-callback UiMoveUpEntryCB \
-autoLock UiMoveUpEntryCB]
VxSetVar $parent moveUp $moveUp
set moveDown [VtPushButton $fileMenu.moveDown \
-label [IntlMsg ENTRY_MENU_DOWN_LBL] \
-mnemonic [IntlMsg ENTRY_MENU_DOWN_MN] \
-shortHelpCallback SaShortHelpCB \
-shortHelpString [IntlMsg ENTRY_MENU_DOWN_SH] \
-callback UiMoveDownEntryCB \
-autoLock UiMoveDownEntryCB]
VxSetVar $parent moveDown $moveDown
VtSeparator $fileMenu.s2
set save [VtPushButton $fileMenu.save \
-label [IntlMsg ENTRY_MENU_SAVE_LBL] \
-mnemonic [IntlMsg ENTRY_MENU_SAVE_MN] \
-shortHelpCallback SaShortHelpCB \
-shortHelpString [IntlMsg ENTRY_MENU_SAVE_SH] \
-callback UiSaveCB \
-autoLock UiSaveCB]
VxSetVar $parent save $save
VtSeparator $fileMenu.s3
set exitMenu $fileMenu
# exit button
VtPushButton $exitMenu.exit \
-label [IntlMsg ENTRY_MENU_EXIT_LBL] \
-mnemonic [IntlMsg ENTRY_MENU_EXIT_MN] \
-shortHelpCallback SaShortHelpCB \
-shortHelpString \ [IntlMsg ENTRY_MENU_EXIT_SH \
[list $appvals(title)]] \
-callback UiCloseCB \
-autoLock UiCloseCB
}
proc UiBuildOptionsMenu {form} {
global appvals
# Define the Pulldown itself
set optionMenu [VtPulldown $form.optionMenu \
-label [IntlMsg OPTIONS_MENU] \
-mnemonic [IntlMsg OPTIONS_MN] \
]
# menu items
# short help
SaShortHelpLoad $appvals(client)
SaShortHelpMenuOptions $optionMenu
# toolbar
if {$appvals(toolbar) && ![VtInfo -charm]} {
UiToolBarBuildMenuOptions $optionMenu
}
VxSetVar $form optionMenu $optionMenu
return $optionMenu
}
proc UiToolBarSetVisibilityCB {{cbs {}}} {
global appvals
set menuBar [VxGetVar $appvals(vtMain) menuBar]
set optionMenu [VxGetVar $menuBar optionMenu]
set toolBarToggle [VxGetVar $optionMenu toolBarToggle]
set visible [VtGetValues $toolBarToggle -value]
set toolBar [VxGetVar $appvals(vtMain) toolBar]
set toolBarFrame [VxGetVar $appvals(vtMain) toolBarFrame]
if {$visible} {
# We *must* show the frame first, then the form
VtShow $toolBarFrame
VtShow $toolBar
} else {
# We *must* hide the form first, then the frame, in order
# to obtain same re-drawing behaviour we get with Sa functions
VtHide $toolBar
VtHide $toolBarFrame
}
SaScreenPolicySet $appvals(client) toolbarVisibility $visible
}
proc UiToolBarBuildMenuOptions {menu} {
global appvals
set toolBarToggle [VtToggleButton $menu.toolBarToggle \
-label [IntlMsg OPTIONS_TOOLBAR] \
-callback UiToolBarSetVisibilityCB \
-shortHelpCallback SaShortHelpCB \
-shortHelpString [IntlMsg OPTIONS_TOOLBAR_SH] \
-value 1]
VxSetVar $menu toolBarToggle $toolBarToggle
}
proc UiBuildToolBar {form top} {
global appvals
set toolBarFrame [VtFrame $form.toolBarFrame \
-topSide $top \
-topOffset 2 \
-leftSide FORM \
-rightSide FORM \
-marginHeight 0 \
-marginWidth 0 \
-horizontalSpacing 0 \
-verticalSpacing 0 \
-shadowType IN]
set toolBarForm [VtForm $toolBarFrame.toolBarForm \
-leftSide FORM \
-rightSide FORM \
-borderWidth 0 \
-marginHeight 0 \
-marginWidth 0 \
-horizontalSpacing 0 \
-verticalSpacing 0]
set addTB [VtPushButton $toolBarForm.addTB \
-label [IntlMsg TB_ADD] \
-topSide FORM \
-topOffset 0 \
-leftSide FORM \
-leftOffset 0 \
-rightOffset 0 \
-bottomSide FORM \
-bottomOffset 0 \
-shortHelpCallback SaShortHelpCB \
-shortHelpString [IntlMsg ENTRY_MENU_ADD_SH] \
-callback UiAddEntryCB \
-autoLock UiAddEntryCB]
VxSetVar $toolBarForm addTB $addTB
set deleteTB [VtPushButton $toolBarForm.deleteTB \
-label [IntlMsg TB_DELETE] \
-topSide FORM \
-leftSide $addTB \
-leftOffset 0 \
-bottomSide FORM \
-bottomOffset 0 \
-shortHelpCallback SaShortHelpCB \
-shortHelpString [IntlMsg ENTRY_MENU_DELETE_SH] \
-callback UiDeleteEntryCB \
-autoLock UiDeleteEntryCB]
VxSetVar $toolBarForm deleteTB $deleteTB
set modifyTB [VtPushButton $toolBarForm.modifyTB \
-label [IntlMsg TB_MODIFY] \
-topSide FORM \
-leftSide $deleteTB \
-leftOffset 10 \
-bottomSide FORM \
-bottomOffset 0 \
-shortHelpCallback SaShortHelpCB \
-shortHelpString [IntlMsg ENTRY_MENU_MODIFY_SH] \
-callback UiModifyEntryCB \
-autoLock UiModifyEntryCB]
VxSetVar $toolBarForm modifyTB $modifyTB
set upTB [VtPushButton $toolBarForm.upTB \
-pixmap [IntlMsg BTN_UP_PX] \
-topSide FORM \
-leftSide $modifyTB \
-leftOffset 10 \
-bottomSide FORM \
-bottomOffset 0 \
-shortHelpCallback SaShortHelpCB \
-shortHelpString [IntlMsg ENTRY_MENU_UP_SH] \
-callback UiMoveUpEntryCB \
-autoLock UiMoveUpEntryCB]
VxSetVar $toolBarForm upTB $upTB
set downTB [VtPushButton $toolBarForm.downTB \
-pixmap [IntlMsg BTN_DOWN_PX] \
-topSide FORM \
-leftSide $upTB \
-leftOffset 0 \
-rightSide NONE \
-bottomSide FORM \
-bottomOffset 0 \
-shortHelpCallback SaShortHelpCB \
-shortHelpString [IntlMsg ENTRY_MENU_DOWN_SH] \
-callback UiMoveDownEntryCB \
-autoLock UiMoveDownEntryCB]
VxSetVar $toolBarForm downTB $downTB
VxSetVar $appvals(vtMain) toolBar $toolBarForm
VxSetVar $appvals(vtMain) toolBarFrame $toolBarFrame
return $toolBarFrame
}
proc DomainGetData {} {
global appvals
set data {}
set maxLength 0
foreach key [Map:List $appvals(fileid)] {
if {[cindex $key 0] == "."} {
set partial TRUE
set hostName [crange $key 1 len]
} else {
set partial FALSE
set hostName $key
}
set hostNameLength [clength $hostName]
if {$hostNameLength > $maxLength} {
set maxLength $hostNameLength
}
set route [Map:Get $appvals(fileid) $key]
set realName [lvarpop route]
keylset entry partial $partial
keylset entry hostName $hostName
keylset entry realName $realName
keylset entry route $route
lappend data $entry
}
set mainList [VxGetVar $appvals(vtMain) mainList]
if {$maxLength < 30} {
set maxLength 30
}
VxSetVar $mainList maxLength $maxLength
return $data
}
proc DomainDelete {entries} {
global appvals
foreach entry $entries {
set partial ""
set hostName ""
keylget entry partial partial
keylget entry hostName hostName
if {$partial == "TRUE"} {
set hostName ".${hostName}"
}
Map:Unset $appvals(fileid) $hostName
}
}
proc DomainAdd {beforeEntry newEntry} {
global appvals
keylget newEntry partial partial
keylget newEntry hostName hostName
keylget newEntry realName realName
keylget newEntry route route
if {$partial == "TRUE"} {
set newKey ".$hostName"
} else {
set newKey $hostName
}
set newData [concat [string trim $realName] $route]
if {$beforeEntry == ""} {
# the file was empty !
Map:Set $appvals(fileid) $newKey $newData
} else {
set beforePartial ""
set beforeHostName ""
keylget beforeEntry partial beforePartial
keylget beforeEntry hostName beforeHostName
if {$beforePartial == "TRUE"} {
set beforeKey ".${beforeHostName}"
} else {
set beforeKey $beforeHostName
}
Map:Insert $appvals(fileid) $newKey $newData $beforeKey
}
}
proc DomainModify {oldEntry newEntry} {
global appvals
keylget newEntry partial partial
keylget newEntry hostName hostName
keylget newEntry realName realName
keylget newEntry route route
if {$partial == "TRUE"} {
set newKey ".${hostName}"
} else {
set newKey $hostName
}
set newData [concat [string trim $realName] $route]
keylget oldEntry partial oldPartial
keylget oldEntry hostName oldHostName
if {$oldPartial == "TRUE"} {
set oldKey ".${oldHostName}"
} else {
set oldKey $oldHostName
}
if {[cequal $newKey $oldKey]} {
Map:Set $appvals(fileid) $newKey $newData
} else {
Map:Insert $appvals(fileid) $newKey $newData $oldKey
Map:Unset $appvals(fileid) $oldKey
}
}
proc DomainSwapPosition {entry1 entry2} {
global appvals
set partial1 ""
set hostName1 ""
keylget entry1 partial partial1
keylget entry1 hostName hostName1
if {$partial1 == "TRUE"} {
set key1 ".${hostName1}"
} else {
set key1 $hostName1
}
set data1 [Map:Get $appvals(fileid) $key1]
set partial2 ""
set hostName2 ""
keylget entry2 partial partial2
keylget entry2 hostName hostName2
if {$partial2 == "TRUE"} {
set key2 ".${hostName2}"
} else {
set key2 $hostName2
}
Map:Unset $appvals(fileid) $key1
Map:Insert $appvals(fileid) $key1 $data1 $key2
}
proc DomainIsModified {} {
global appvals
if {$appvals(fileid) != -1} {
return [Map:Modified $appvals(fileid)]
} else {
return 0
}
}
proc DomainEntryExists {hostname} {
global appvals
set allKeys [string tolower [Map:List $appvals(fileid)]]
if {[lsearch -exact $allKeys [string tolower $hostname]] == -1 && \
[lsearch -exact $allKeys [string tolower ".${hostname}"]] == -1} {
return 0
} else {
return 1
}
}
proc DomainSetMainListLabel {maxHostNameLength} {
global appvals
set mainList [VxGetVar $appvals(vtMain) mainList]
if {[VtInfo -charm]} {
set labelList [list \
[IntlMsg COLUMN_PARTIAL_LBL_CHARM] \
[IntlMsg COLUMN_HOST_LBL] \
[IntlMsg COLUMN_ROUTE_LBL]]
} else {
set labelList [list \
[IntlMsg COLUMN_PARTIAL_LBL] \
[IntlMsg COLUMN_HOST_LBL] \
[IntlMsg COLUMN_ROUTE_LBL]]
}
if {[VtInfo -charm]} {
# add 1 for the right margin width
set fieldLength [expr $maxHostNameLength + 1]
# For charm, we can't really go beyond 60 chars for the
# hostname portion of the label
if {$fieldLength > 60} {
set fieldLength 60
}
set labelFormat "%-3s%-${fieldLength}s%-20s"
set label [format $labelFormat \
[lindex $labelList 0] \
[lindex $labelList 1] \
[lindex $labelList 2]]
set header [VxGetVar $appvals(vtMain) header]
VtSetValues $header -label $label
}
# Try to adjust the length to compensate for variable char widths,
# and then add 1 for right margin
set fieldLength [expr [AdjustFieldLength $maxHostNameLength] + 1]
VtSetValues $mainList -labelFormatList [list \
[list STRING 1 14 10] \
[list STRING $fieldLength] \
[list STRING 20]]
VtSetValues $mainList -labelList $labelList
}
proc DomainBuildMainList {form top} {
global appvals
if {[VtInfo -charm]} {
set labelList [list \
[IntlMsg COLUMN_PARTIAL_LBL_CHARM] \
[IntlMsg COLUMN_HOST_LBL] \
[IntlMsg COLUMN_ROUTE_LBL]]
set labelFormat "%-3s%-20s%-20s"
set label [format $labelFormat \
[lindex $labelList 0] \
[lindex $labelList 1] \
[lindex $labelList 2]]
set header [VtLabel $form.header \
-labelLeft \
-leftSide FORM \
-leftOffset 3 \
-rightSide FORM \
-topSide $top \
-topOffset 1\
-bottomSide NONE \
-label $label]
VxSetVar $form header $header
set top $header
}
set mainList [VtDrawnList $form.mainList \
-MOTIF_rows 10 -CHARM_rows 25 \
-MOTIF_columns 80 -CHARM_columns 20 \
-horizontalScrollBar TRUE \
-leftSide FORM \
-MOTIF_leftOffset 5 -CHARM_leftOffset 0 \
-rightSide FORM \
-MOTIF_rightOffset 5 -CHARM_rightOffset 0 \
-topSide $top \
-MOTIF_topOffset 10 -CHARM_topOffset 0 \
-bottomSide NONE \
-selection MULTIPLE \
-callback DomainMainListCB \
-defaultCallback DomainMainListDoubleCB \
-autoLock {DomainMainListDoubleCB}]
VxSetVar $form mainList $mainList
DomainSetMainListLabel 30
return $mainList
}
proc DomainMainListCB {cbs} {
UiMainListCB $cbs
}
proc DomainMainListDoubleCB {cbs} {
UiMainListDoubleCB $cbs
}
proc DomainInit {} {
global appvals
set appvals(title) [IntlMsg TITLE $appvals(filename)]
set appvals(object) [IntlMsg OBJECT]
set appvals(objectmn) [IntlMsg OBJECT_MN]
set appvals(itemname) [IntlMsg ITEMS]
}
proc DomainWrite {} {
global appvals
global errorInfo
#
# commit the changes to file
#
# force a write since Map:Write will usually only write if
# modifcations are made
Map:ForceWrites $appvals(fileid)
if {[ErrorCatch errStack 0 "Map:Write $appvals(fileid)" result]} {
ErrorPush errStack 0 [IntlErrId NONSTDCMD] [list $errorInfo]
ErrorPush errStack 1 [IntlErrId WRITE] $appvals(filename)
}
#
# compile the database
#
set cmd [list exec /etc/mail/makemap hash $appvals(filename) < $appvals(filename) >& /dev/null]
if {[ErrorCatch errStack 0 $cmd result]} {
ErrorPush errStack 0 [IntlErrId NONSTDCMD] [list $errorInfo]
ErrorPush errStack 1 [IntlErrId DATABASE] $appvals(filename).db
}
}
set appvals(script) [file tail [info script]] ;# argv[0]: UNIX command name
set appvals(client) $appvals(script) ;# widget strings, preferences
set appvals(filename) {} ;# filename of domain table
set appvals(fileid) -1 ;# backend file id of table
set appvals(hostname) localhost ;# name of host being managed
proc Exit {{code 0}} {
# Final exit tasks
exit $code
}
proc Usage {} {
global appvals
set usage [IntlErr USAGE $appvals(script)]
puts stderr $usage
}
proc ParseCommandLine {} {
global argv argc optarg opterr optind appvals
# scan for commandline flags
set optString "f:h:"
set argc [llength $argv]
if {$argc == 0} {
Usage; Exit 1
}
set opterr 0
while {[set opt [getopt $argc $argv $optString]] != -1} {
switch $opt {
{f} {
set appvals(filename) $optarg
}
{h} {
set appvals(hostname) $optarg
}
{?} {
Usage; Exit 1
}
}
}
# process commandline arguments
set optCount [expr "$argc - $optind"]
if {$optCount > 0} {
Usage; Exit 1
}
if {"$appvals(filename)" == ""} {
Usage; Exit 1
}
}
proc Main {} {
global appvals errorInfo
# Collect command line options
ParseCommandLine
# Initialize UI, build main form, present initial view
# Init a few globals first
DomainInit
UiStart
# Main UI is now presented and Locked
# Time-consuming startup operations can now take place with
# optional status messages
#
# + collect data to populate main form widgets
# + populate main form widgets with live data
SaStatusBarSet \
[VxGetVar $appvals(vtMain) statusBar] [IntlMsg INIT]
# Show/hide the toolbar, depending on screen policy
if {! [VtInfo -charm]} {
set cmd "set visibility \[SaScreenPolicyGet $appvals(client) toolbarVisibility\]"
if {[ErrorCatch errStack 0 $cmd errMsg] != 0} {
set visibility 1
}
set menuBar [VxGetVar $appvals(vtMain) menuBar]
set optionMenu [VxGetVar $menuBar optionMenu]
set toolBarToggle [VxGetVar $optionMenu toolBarToggle]
set toolBar [VxGetVar $appvals(vtMain) toolBar]
set toolBarFrame [VxGetVar $appvals(vtMain) toolBarFrame]
VtSetValues $toolBarToggle -value $visibility
UiToolBarSetVisibilityCB
}
# if file does not exist, let the user know
if {![file exists $appvals(filename)]} {
set main $appvals(vtMain)
set dialog [VtInformationDialog $main.exist \
-message [IntlMsg FILE_DOESNT_EXIST] \
-ok]
VtShow $dialog
}
# if file is a directory, show error and exit
if {[file isdirectory $appvals(filename)]} {
set main $appvals(vtMain)
set dialog [VtErrorDialog $main.error \
-message [IntlErr DIRECTORY $appvals(filename)] \
-ok -okCallback UiCloseCB -wmCloseCallback UiCloseCB]
VtShow $dialog
VtUnLock
VtMainLoop
return
}
# Open the file and read in the data to back end structures
if {[ErrorCatch errStack 0 "Map:Open $appvals(filename)" result]} {
ErrorPush errStack 0 [IntlErrId NONSTDCMD] [list $errorInfo]
ErrorPush errStack 0 [IntlErrId LOAD] $appvals(filename)
VtUnLock
UiDisplayErrorStacks Main $errStack UiCloseCB
} else {
set appvals(fileid) $result
}
# Refresh main form data
UiRefreshCB
# Select first item, if exists
set mainList [VxGetVar $appvals(vtMain) mainList]
if {![lempty [VtDrawnListGetItem $mainList -all]]} {
VtDrawnListSelectItem $mainList -position 1
}
# update the count label
UiUpdateCountLabel
# Set initial focus (list or menu bar)
UiSetAppFocus
# Set sensitivity of all main screen ui selection devices
UiSensitizeMainFunctions
# Setup complete
# Wait for user events
SaStatusBarClear [VxGetVar $appvals(vtMain) statusBar]
VtUnLock
VtMainLoop
}
proc CloseWithUi {} {
set saveConfirmDlg [UiBuildSaveConfirmDialog]
VtShow $saveConfirmDlg
}
proc CloseAfterUi {} {
Exit
}
proc Refresh {} {
global appvals
# Populate main form data here
set data {}
# TODO
# Setup simple example using the "who" module
# Except for the following line, Refresh should be generic
# and usable as is.
# load Ui
set data [DomainGetData]
UiMainListSetItems $data
}
ErrorTopLevelCatch {Main} $appvals(script)