home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 March B / SCO_CASTOR4RRT.iso / scoadmin / root.3 / etc / mail / admin / domain / domain~
Text File  |  1998-08-19  |  78KB  |  2,514 lines

  1. #!/bin/osavtcl
  2. #******************************************************************************
  3. #
  4. #    Copyright (C) 1993-1997 The Santa Cruz Operation, Inc.
  5. #        All Rights Reserved.
  6. #
  7. #    The information in this file is provided for the exclusive use of
  8. #    the licensees of The Santa Cruz Operation, Inc.  Such users have the
  9. #    right to use, modify, and incorporate this code into other products
  10. #    for purposes authorized by the license agreement provided they include
  11. #    this notice and the associated copyright notice with any such product.
  12. #    The information in this file is provided "AS IS" without warranty.
  13. #
  14. #===============================================================================
  15. loadlibindex /usr/lib/sysadm.tlib
  16. proc SCO_MAIL_ADMIN_DOMAIN_MSGS {} {}
  17. global SCO_MAIL_ADMIN_DOMAIN_MSGS
  18. set SCO_MAIL_ADMIN_DOMAIN_MSGS(@catalog@) {domain.cat@mail 1}
  19. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_HELPBOOK) {1 domain}
  20. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_TITLE) {2 {Domain Table File %1$s}}
  21. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ITEMS) {3 Entries}
  22. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_FILE_DOESNT_EXIST) {4 {File does not exist}}
  23. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_OK) {5 OK}
  24. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_CANCEL) {6 Cancel}
  25. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_HELP) {7 Help}
  26. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_COLUMN_PARTIAL_LBL) {8 *}
  27. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_COLUMN_PARTIAL_LBL_CHARM) {9 x}
  28. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_COLUMN_PARTIAL_NONE) {10 { }}
  29. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_COLUMN_HOST_LBL) {11 Host}
  30. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_COLUMN_ROUTE_LBL) {12 {Route Via}}
  31. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_OBJECT) {13 Entry}
  32. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_OBJECT_MN) {14 E}
  33. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_ADD_LBL) {15 Add...}
  34. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_ADD_MN) {16 A}
  35. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_ADD_SH) {17 {Add a domain table entry...}}
  36. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_DELETE_LBL) {18 Delete}
  37. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_DELETE_MN) {19 D}
  38. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_DELETE_SH) {20 {Delete a domain table entry}}
  39. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_MODIFY_LBL) {21 Modify...}
  40. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_MODIFY_MN) {22 M}
  41. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_MODIFY_SH) {23 {Modify a domain table entry...}}
  42. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_UP_LBL) {24 {Move Up}}
  43. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_UP_MN) {25 U}
  44. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_UP_SH) {26 {Move a domain table entry up in order}}
  45. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_DOWN_LBL) {27 {Move Down}}
  46. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_DOWN_MN) {28 o}
  47. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_DOWN_SH) {29 {Move a domain table entry down in order}}
  48. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_SAVE_LBL) {30 Save}
  49. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_SAVE_MN) {31 S}
  50. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_SAVE_SH) {32 {Save any changes}}
  51. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_EXIT_LBL) {33 Exit}
  52. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_EXIT_MN) {34 x}
  53. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ENTRY_MENU_EXIT_SH) {35 {Exit %s}}
  54. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_OPTIONS_MENU) {36 Options}
  55. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_OPTIONS_MN) {37 O}
  56. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_OPTIONS_TOOLBAR) {38 Toolbar}
  57. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_OPTIONS_TOOLBAR_SH) {39 {Show/hide Toolbar}}
  58. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ADD_TITLE) {40 {Add Domain Table Entry}}
  59. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_MODIFY_TITLE) {41 {Modify Domain Table Entry}}
  60. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_NAME_LBL) {42 Name}
  61. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_NAME_SH) {43 {Enter the host name to be matched for this entry}}
  62. set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_NAME_MISSING) {44 {No host name specified for \"Name\" field}}
  63. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_REAL_NAME_LBL) {45 {Real Name}}
  64. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_REAL_NAME_SH) {46 {Enter the real host name mail will be sent to}}
  65. set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_REAL_NAME_MISSING) {47 {No host name specified for \"Real Name\" field}}
  66. set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_NAME_SPACE) {48 {A host name may not contain a space}}
  67. set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_NAME_DUPLICATE) {49 {An entry for host name \"%1$s\" already exists}}
  68. set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_NUMERIC) {50 {Subdomain lookups are not allowed on numeric addresses}}
  69. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ROUTE_LIST_LBL) {51 {Route to host:}}
  70. set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_ENTER_NAME) {52 {You did not enter a host name}}
  71. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ROUTE_ADD_BTN_LBL) {53 {  Add...  }}
  72. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ROUTE_ADD_BTN_SH) {54 {Add a host to the route}}
  73. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ROUTE_DELETE_BTN_LBL) {55 {  Delete  }}
  74. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ROUTE_DELETE_BTN_SH) {56 {Delete a host from the route}}
  75. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ROUTE_UP_BTN_SH) {57 {Move this host name up in the route}}
  76. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ROUTE_DOWN_BTN_SH) {58 {Move this host name down in the route}}
  77. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_DO_PARTIAL_LBL) {59 {Do subdomain lookups}}
  78. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_DO_PARTIAL_SH) {60 {Allow subdomain lookups on the host name}}
  79. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ROUTE_ADD_DLG_TITLE) {61 {Add To Route}}
  80. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ROUTE_ADD_DLG_TEXT_LBL) {62 {Enter host name(s):}}
  81. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_ROUTE_ADD_DLG_BTN_LBL) {63 Select...}
  82. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_SAVE_CONFIRM_TITLE) {64 {Save Changes?}}
  83. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_SAVE_CONFIRM_QUERY) {65 {Do you wish to save the changes made?}}
  84. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_SAVE_CONFIRM_BTN_YES) {66 Yes}
  85. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_SAVE_CONFIRM_BTN_NO) {67 No}
  86. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_SAVE_CONFIRM_BTN_CANCEL) {68 Cancel}
  87. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_TB_ADD) {69 Add...}
  88. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_TB_DELETE) {70 Delete}
  89. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_TB_MODIFY) {71 Modify...}
  90. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_DL_ARROW_PX) {72 /etc/mail/admin/px/arrow.px}
  91. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_DL_CHECK_PX) {73 /etc/mail/admin/px/check.px}
  92. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_BTN_UP_PX) {74 /etc/mail/admin/px/prev.px}
  93. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_BTN_DOWN_PX) {75 /etc/mail/admin/px/next.px}
  94. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_SELECTED) {76 Selected}
  95. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_COUNT_LABEL_STR) {77 {%1$s %2$s, %3$s %4$s}}
  96. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_PARTIAL_LABEL_STR) {78 {*  = entry allows subdomain lookups on the host name}}
  97. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_PARTIAL_LABEL_STR_CHARM) {79 {x  = entry allows subdomain lookups on the host name}}
  98. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_INIT) {80 Initializing...}
  99. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_REFRESH) {81 {Loading domain table data...}}
  100. set SCO_MAIL_ADMIN_DOMAIN_MSGS(MSG_SAVE) {82 {Saving domain table data...}}
  101. set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_USAGE) {83 {Usage: %1$s -f filename [-h hostname]}}
  102. set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_DIRECTORY) {84 {\"%1$s\" is a directory, not a file}}
  103. set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_DATABASE) {85 {Unable to create domain table database\n\"%1$s\"}}
  104. set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_WRITE) {86 {Unable to write domain table file\n\"%1$s\"}}
  105. set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_LOAD) {87 {Unable to load domain table file\n\"%1$s\"}}
  106. set SCO_MAIL_ADMIN_DOMAIN_MSGS(ERR_NONSTDCMD) {88 %s}
  107. set appvals(intlpre) SCO_MAIL_ADMIN_DOMAIN        ;# i10n msg prefix
  108. proc IntlMsg {id {argList {}}} {
  109.     global appvals
  110.     return [IntlLocalizeMsg $appvals(intlpre)_MSG_$id $argList]
  111. }
  112. proc IntlErr {id {argList {}}} {
  113.     global appvals
  114.     return [IntlLocalizeMsg $appvals(intlpre)_ERR_$id $argList]
  115. }
  116. proc IntlErrId {id} {
  117.     global appvals
  118.     return $appvals(intlpre)_ERR_$id
  119. }
  120. proc ConfigFile:Open {} {
  121.     global Config_next
  122.     if {![info exists Config_next]} {
  123.     set Config_next 0
  124.     }
  125.     set file "config$Config_next"
  126.     incr Config_next
  127.     upvar #0 Config_${file}_next file_next
  128.     set file_next "1.0"
  129.     return $file
  130. }
  131. proc ConfigFile:Close {file} {
  132.     upvar #0 Config_$file fileList
  133.     upvar #0 Config_${file}_next file_next
  134.     unset file_next
  135.     foreach line [ConfigFile:GetList $file] {
  136.     unset fileList($line)
  137.     }
  138. }
  139. proc ConfigFile:Compare {line1 line2} {
  140.     set subLine1 [ctoken line1 "."]
  141.     set subLine2 [ctoken line2 "."]
  142.     if {$subLine1 == "" && $subLine2 == ""} {
  143.     return 0
  144.     } elseif {$subLine1 == ""} {
  145.     return -1
  146.     }  elseif {$subLine2 == ""} {
  147.     return 1
  148.     } elseif {$subLine1 < $subLine2} {
  149.     return -1
  150.     } elseif {$subLine1 > $subLine2} {
  151.     return 1
  152.     } else {
  153.     set line1 [string trimleft $line1 "."]
  154.     set line2 [string trimleft $line2 "."]
  155.     return [ConfigFile:Compare $line1 $line2]
  156.     }
  157. }
  158. proc ConfigFile:ReplaceLine {file line type id dataVar} {
  159.     upvar #0 Config_$file fileList
  160.     upvar #0 Config_${file}_next file_next
  161.     upvar $dataVar data
  162.     keylset fileList($line) type $type
  163.     keylset fileList($line) data $data
  164.     keylset fileList($line) id $id
  165.     if {[ConfigFile:Compare $line $file_next] == 1} {
  166.     set temp $line
  167.     set file_next [ctoken temp "."]
  168.     incr file_next
  169.     set file_next "${file_next}.0"
  170.     }
  171. }
  172. proc ConfigFile:AppendLine {file line type id dataVar} {
  173.     upvar #0 Config_$file fileList
  174.     upvar #0 Config_${file}_next file_next
  175.     upvar $dataVar data
  176.     if {$line == -1} {
  177.     set line $file_next
  178.     set temp [ctoken file_next "."]
  179.     incr temp
  180.     set file_next "${temp}.0"
  181.     } else {
  182.     set found 0
  183.     set left [ctoken line "."]
  184.     set right [ctoken line "."]
  185.     if {$right == "0"} {
  186.         set tryNext $left
  187.         incr tryNext
  188.         set tryNext "${tryNext}.0"
  189.         if {![info exists fileList($tryNext)]} { 
  190.         set found 1
  191.         }
  192.     }
  193.     if {!$found} {
  194.         set lastDigit [cindex $right end]
  195.         if {$lastDigit < 9} {
  196.             incr lastDigit
  197.             set tryNext "${left}.[csubstr $right 0 end]${lastDigit}"
  198.             if {![info exists fileList($tryNext)]} {
  199.             set found 1
  200.             }    
  201.         }
  202.     }
  203.     if {!$found} {
  204.         set leadingZeros ""
  205.         set tryNext "${left}.${right}.1"
  206.         while {[info exists fileList($tryNext)]} {
  207.         set leadingZeros "${leadingZeros}.0"
  208.         set tryNext "${left}.${right}${leadingZeros}.1"
  209.         }
  210.     }
  211.     set line $tryNext
  212.     }
  213.     keylset fileList($line) type $type
  214.     keylset fileList($line) id $id
  215.     keylset fileList($line) data $data
  216.     if {[string compare $line $file_next] == 1} {
  217.     set temp $line
  218.     set file_next [ctoken temp "."]
  219.     incr file_next
  220.     set file_next "${file_next}.0"
  221.     }
  222.     return $line
  223. }
  224. proc ConfigFile:GetLine {file line typeVar idVar dataVar} {
  225.     upvar #0 Config_$file fileList
  226.     upvar $typeVar type
  227.     upvar $idVar id
  228.     upvar $dataVar data
  229.     if {![info exists fileList($line)]} {
  230.     set type {}
  231.     set id {}
  232.     set data {}
  233.     return -1
  234.     }
  235.     keylget fileList($line) type type
  236.     keylget fileList($line) id id
  237.     keylget fileList($line) data data
  238.     return 0
  239. }
  240. proc ConfigFile:RemoveLine {file line} {
  241.     upvar #0 Config_$file fileList
  242.     if {![info exists fileList($line)]} {
  243.     # already gone
  244.     return
  245.     }
  246.     unset fileList($line)
  247. }
  248. proc ConfigFile:GetList {file} {
  249.     upvar #0 Config_$file fileList
  250.     if {![info exists fileList]} {
  251.     return {}
  252.     }
  253.     return [lsort -command ConfigFile:Compare [array names fileList]]
  254. }
  255. proc Table:ProcessLine {fileID type id data} {
  256.     global Table_lastType Table_lastID
  257.     set lineNum [ConfigFile:AppendLine $fileID -1 $type $id data]
  258.     if {[Table:GetOption $fileID makelower] != {}} {
  259.     set id [string tolower $id]
  260.     }
  261.     case $type {
  262.     CONTINUATION {
  263.         set type $Table_lastType
  264.         set id $Table_lastID
  265.     }
  266.     COMMENT {
  267.     }
  268.     default {
  269.         set Table_lastType $type
  270.         set Table_lastID $id
  271.     }
  272.     }
  273.     if {$id != {}} {
  274.     upvar #0 Table_${fileID}_$type typeList
  275.     lappend typeList($id) $lineNum
  276.     }
  277. }
  278. proc Table:Read {fileName callBack mode} {
  279.     global Table_info
  280.     if {[info exists Table_info($fileName.ID)]} {
  281.     return $Table_info($fileName.ID)
  282.     }
  283.     set fileID [ConfigFile:Open]
  284.     set Table_info($fileID.mode) $mode
  285.     if {![file exists $fileName]} {
  286.     return $fileID
  287.     }
  288.     set fp [open $fileName r]
  289.     set Table_info($fileName.ID) $fileID
  290.     set Table_info($fileID.fileName) $fileName
  291.     eval $callBack $fileID $fp
  292.     close $fp
  293.     return $fileID
  294. }
  295. proc Table:Write {fileID {fileName {}} {callBack {}}} {
  296.     global Table_info
  297.     if {[info exists Table_info($fileID.deferred)]} {
  298.     return
  299.     }
  300.     if {![info exists Table_info($fileID.modified)] && $fileName == {}} {
  301.     return
  302.     }
  303.     if {$callBack == {}} {
  304.     set callBack $Table_info($fileID.writeCB)
  305.     }
  306.     if {$fileName == {}} {
  307.     set fileName $Table_info($fileID.fileName)
  308.     set clearModified 1
  309.     } else {
  310.     set clearModified 0
  311.     }
  312.     #
  313.     # If the file exists, make sure the new file has the
  314.     # same owner and perms.  Otherwise, make sure the
  315.     # parent directory exists.
  316.     #
  317.     if {[file exists $fileName]} {
  318.     file stat $fileName info
  319.     set Table_info($fileID.uid) $info(uid)
  320.     set Table_info($fileID.gid) $info(gid)
  321.     set Table_info($fileID.mode) $info(mode)
  322.     } else {
  323.     set directory [file dirname $fileName]
  324.     set oldUmask [umask]
  325.     umask 0222
  326.     if {![file isdirectory $directory]} {
  327.         mkdir -path $directory
  328.     }
  329.     umask $oldUmask
  330.     }
  331.     set fp [open ${fileName}.new w]
  332.     chmod $Table_info($fileID.mode) ${fileName}.new
  333.     if {[info exists Table_info($fileID.uid)]} {
  334.     chown [list $Table_info($fileID.uid) $Table_info($fileID.gid)] \
  335.         ${fileName}.new
  336.     }
  337.     foreach line [ConfigFile:GetList $fileID] {
  338.     if {[ConfigFile:GetLine $fileID $line type id data] != 0} {
  339.         continue
  340.     }
  341.     eval "$callBack $fileID $fp {$type} {$id} {$data}"
  342.     }
  343.     close $fp
  344.     if {[file exists $fileName]} {
  345.     unlink $fileName
  346.     }
  347.     frename ${fileName}.new $fileName
  348.     if {$clearModified} {
  349.     unset Table_info($fileID.modified)
  350.     }
  351. }
  352. proc Table:Open {fileName readCB writeCB {mode 0666}} {
  353.     global Table_info
  354.     set fileID [Table:Read $fileName $readCB $mode]
  355.     set Table_info($fileID.fileName) $fileName
  356.     set Table_info($fileID.readCB) $readCB
  357.     set Table_info($fileID.writeCB) $writeCB
  358.     set Table_info($fileName.ID) $fileID
  359.     return $fileID
  360. }
  361. proc Table:Close {fileID {fileName {}}} {
  362.     global Table_info
  363.     if {![info exists Table_info($fileID.fileName)]} {
  364.     return
  365.     }
  366.     if {[info exists Table_info($fileID.deferred)]} {
  367.     unset Table_info($fileID.deferred)
  368.     }
  369.     Table:Write $fileID $fileName $Table_info($fileID.writeCB)
  370.     if {$fileName == {}} {
  371.     set fileName $Table_info($fileID.fileName)
  372.     }
  373.     unset Table_info($fileID.fileName)
  374.     unset Table_info($fileName.ID)
  375.     ConfigFile:Close $fileID
  376. }
  377. proc Table:CloseNoWrite {fileID {fileName {}}} {
  378.     global Table_info
  379.     if {![info exists Table_info($fileID.fileName)]} {
  380.     return
  381.     }
  382.     if {[info exists Table_info($fileID.deferred)]} {
  383.     unset Table_info($fileID.deferred)
  384.     }
  385.     if {$fileName == {}} {
  386.     set fileName $Table_info($fileID.fileName)
  387.     }
  388.     unset Table_info($fileID.fileName)
  389.     unset Table_info($fileName.ID)
  390.     ConfigFile:Close $fileID
  391. }
  392. proc Table:DeferWrites {fileID} {
  393.     global Table_info
  394.     set Table_info($fileID.deferred) 1
  395. }
  396. proc Table:ForceWrites {fileID} {
  397.     global Table_info
  398.     if {[info exists Table_info($fileID.deferred)]} {
  399.     unset Table_info($fileID.deferred)
  400.     }
  401.     set Table_info($fileID.modified) 1
  402. proc Table:SetOption {fileID option {value 1}} {
  403.     global Table_options
  404.     set Table_options($fileID.$option) $value
  405. }
  406. proc Table:HasOption {fileID option} {
  407.     return [info exists Table_options($fileID.$option)]
  408. }
  409. proc Table:GetOption {fileID option} {
  410.     global Table_options
  411.     if {![info exists Table_options($fileID.$option)]} {
  412.     return {}
  413.     }
  414.     return $Table_options($fileID.$option)
  415. }
  416. proc Table:Modified {fileID} {
  417.     global Table_info
  418.     if {[info exists Table_info($fileID.modified)]} {
  419.     return $Table_info($fileID.modified)
  420.     } else {
  421.     return 0
  422.     }
  423. }
  424. proc Table:GetLineList {fileID type {idList {}}} {
  425.     upvar #0 Table_${fileID}_$type typeList
  426.     if {![info exists typeList]} {
  427.     return {}
  428.     }
  429.     if {$idList == {}} {
  430.     set idList [array names typeList]
  431.     }
  432.     set lineList {}
  433.     foreach id $idList {
  434.     if {[info exists typeList($id)]} {
  435.         append lineList " $typeList($id)"
  436.     }
  437.     }
  438.     return [lsort -command ConfigFile:Compare $lineList]
  439. }
  440. proc Table:Get {fileID type id {separator {}}} {
  441.     upvar #0 Table_${fileID}_$type typeList
  442.     if {[Table:GetOption $fileID makelower] != {}} {
  443.     set id [string tolower $id]
  444.     }
  445.     set value {}
  446.     if {![info exists typeList($id)]} {
  447.     return $value
  448.     }
  449.     set numLines [llength [Table:GetLineList $fileID $type $id]]
  450.     set thisLine 1
  451.     foreach line $typeList($id) {
  452.     ConfigFile:GetLine $fileID $line dummy dummy data
  453.     if {$thisLine == $numLines} {
  454.         append value "$data"
  455.     } else {
  456.         set data [string trim $data "$separator"]
  457.         append value "$data$separator"
  458.     }
  459.     incr thisLine
  460.     }
  461.     set value [string trimleft $value $separator]
  462.     return $value
  463. }
  464. proc Table:Set {fileID type id data} {
  465.     upvar #0 Table_${fileID}_${type} typeList
  466.     global Table_info
  467.     global Table_lastType Table_lastID
  468.     set name $id
  469.     if {[Table:GetOption $fileID makelower] != {}} {
  470.     set id [string tolower $id]
  471.     }
  472.     if {[info exists typeList($id)]} {
  473.     foreach line $typeList($id) {
  474.         ConfigFile:RemoveLine $fileID $line
  475.     }
  476.     set line [lindex $typeList($id) 0]
  477.     unset typeList($id)
  478.     } else {
  479.     if {[set lineList [Table:GetLineList $fileID $type]] != {}} {
  480.         set line [lindex $lineList end]
  481.     } else {
  482.         if {[Table:GetOption $fileID newFirst] == 1} {
  483.         set line 0
  484.         } else {
  485.         set line -1
  486.         }
  487.     }
  488.     }
  489.     lappend typeList($id) [ConfigFile:AppendLine $fileID $line \
  490.     $type $name data]
  491.     set Table_lastType $type
  492.     set Table_lastID $id
  493.     set Table_info($fileID.modified) 1
  494. }
  495. proc Table:Unset {fileID type id} {
  496.     upvar #0 Table_${fileID}_$type typeList
  497.     global Table_info
  498.     if {[Table:GetOption $fileID makelower] != {}} {
  499.     set id [string tolower $id]
  500.     }
  501.     if {![info exists typeList($id)]} {
  502.     return
  503.     }
  504.     foreach line $typeList($id) {
  505.     ConfigFile:RemoveLine $fileID $line
  506.     }
  507.     unset typeList($id)
  508.     set Table_info($fileID.modified) 1
  509. }
  510. proc Table:AppendLine {fileID type id value {line {}}} {
  511.     global Table_lastType Table_lastID
  512.     global Table_info
  513.     if {$type == "CONTINUATION"} {
  514.     upvar #0 Table_${fileID}_$Table_lastType typeList
  515.     } else {
  516.     upvar #0 Table_${fileID}_$type typeList
  517.     }
  518.     if {[Table:GetOption $fileID makelower] != {}} {
  519.     set id [string tolower $id]
  520.     }
  521.     if {$line == ""} {
  522.     if {[info exists typeList($id)]} {
  523.         set line [lindex $typeList($id) end]
  524.     } else {
  525.         if {[set lineList [Table:GetLineList $fileID $type]] == {}} {
  526.         set line [lindex $lineList end]
  527.         } else {
  528.         if {[Table:GetOption $fileID newFirst] == 1} {
  529.             set line 0
  530.         } else {
  531.             set line -1
  532.         }
  533.         }
  534.     }
  535.     }
  536.     if {$type == "CONTINUATION"} {
  537.     lappend typeList($id) \
  538.         [ConfigFile:AppendLine $fileID $line $type {} value]
  539.     } else {
  540.     lappend typeList($id) \
  541.         [ConfigFile:AppendLine $fileID $line $type $id value]
  542.     }
  543.     set Table_info($fileID.modified) 1
  544. }
  545. proc Table:RemoveLine {fileID type id deleteLine} {
  546.     upvar #0 Table_${fileID}_$type typeList
  547.     global Table_info
  548.     if {[Table:GetOption $fileID makelower] != {}} {
  549.     set id [string tolower $id]
  550.     }
  551.     if {![info exists typeList($id)]} {
  552.     return
  553.     }
  554.     set index 0
  555.     foreach line $typeList($id) {
  556.     if {$line == $deleteLine} {
  557.         lvarpop typeList($id) $index
  558.         ConfigFile:RemoveLine $fileID $line
  559.         break
  560.     }
  561.     incr index
  562.     }
  563.     set Table_info($fileID.modified) 1
  564. }
  565. proc Table:ReplaceLine {fileID type replaceLine id data} {
  566.     global Table_info
  567.     upvar #0 Table_${fileID}_$type typeList
  568.     if {[ConfigFile:GetLine $fileID $replaceLine oldType oldId oldData] == 0} {
  569.     if {$oldId != ""} {
  570.             upvar #0 Table_${fileID}_$oldType oldTypeList
  571.         set index [lsearch -exact $oldTypeList($oldId) $replaceLine]
  572.         if {$index != -1} {
  573.         lvarpop oldTypeList($oldId) $index
  574.         if {[lempty $oldTypeList($oldId)]} {
  575.             unset oldTypeList($oldId)
  576.         }
  577.         }
  578.     }
  579.     }
  580.     ConfigFile:ReplaceLine $fileID $replaceLine $type $id data
  581.     if {$id != ""} {
  582.     if {![info exists typeList($id)]} {
  583.         set typeList($id) {}
  584.     }
  585.     lappend typeList($id) $replaceLine
  586.     }
  587.     set Table_info($fileID.modified) 1
  588. }
  589. proc Table:List {fileID type {ordered 0}} {
  590.     upvar #0 Table_${fileID}_$type typeList
  591.     if {![info exists typeList]} {
  592.     return {}
  593.     }
  594.     if {[Table:GetOption $fileID makelower] == {} && $ordered == 0} {
  595.     return [array names typeList]
  596.     }
  597.     #
  598.     # We have to go get the original ids from before they were converted 
  599.     # to lower case, or they want the ids in the order they appear anyway.
  600.     #
  601.     set returnList {}
  602.     foreach line [Table:GetLineList $fileID $type] {
  603.     ConfigFile:GetLine $fileID $line dummy id dummy
  604.     append returnList " $id"
  605.     }
  606.     return [string trimleft $returnList]
  607. }
  608. proc Map:ReadCB {fileID fp} {
  609.     set context [scancontext create]
  610.     scanmatch $context {^([^#][^     ]*)([     ].*)} {
  611.     Table:ProcessLine $fileID entry $matchInfo(submatch0) \
  612.         $matchInfo(submatch1)
  613.     }
  614.     scanmatch $context {
  615.     Table:ProcessLine $fileID COMMENT {} $matchInfo(line)
  616.     }
  617.     scanfile $context $fp
  618.     scancontext delete $context
  619. }
  620. proc Map:WriteCB {fileID fp type id data} {
  621.     case $type {
  622.     entry {
  623.         puts $fp "${id}${data}"
  624.     }
  625.     COMMENT {
  626.         puts $fp $data
  627.     }
  628.     }
  629. }
  630. proc Map:Open {fileName {mode 0644}} {
  631.     return [Table:Open $fileName Map:ReadCB Map:WriteCB $mode]
  632. }
  633. proc Map:Write {fileID {fileName {}}} {
  634.     return [Table:Write $fileID $fileName]
  635. }
  636. proc Map:ForceWrites {fileID} {
  637.     return [Table:ForceWrites $fileID]
  638. }
  639. proc Map:Get {fileID id} {
  640.     return [string trimleft [Table:Get $fileID entry $id]]
  641. }
  642. proc Map:Set {fileID id data} {
  643.     if {![string match {[     ]*} $data]} {
  644.     set data "    $data"
  645.     }
  646.     return [Table:Set $fileID entry $id $data]
  647. }
  648. proc Map:Unset {fileID id} {
  649.     return [Table:Unset $fileID entry $id]
  650. }
  651. proc Map:List {fileID} {
  652.     set lineOrdered 1
  653.     return [Table:List $fileID entry $lineOrdered]
  654. }
  655. proc Map:Insert {fileID id data idBefore} {
  656.     if {![string match {[     ]*} $data]} {
  657.     set data "    $data"
  658.     }
  659.     # there should really not be duplicate entry ids (keys),
  660.     # but in case a duplicate was hand edited in, we pick the first one
  661.     # as it is the only one that counts in the map file
  662.     set lineBefore [lindex [Table:GetLineList $fileID entry $idBefore] 0]
  663.     # put the new entry after $idBefore
  664.     Table:AppendLine $fileID entry $id $data $lineBefore 
  665. }
  666. proc Map:Modified {fileID} {
  667.     return [Table:Modified $fileID]
  668. }
  669. set appvals(vtApp)    {}        ;# VtOpen return; generally not used 
  670. set appvals(vtMain)    {}        ;# widget string of main dialog
  671. set appvals(toolbar)         1        ;# toolbar
  672. set appvals(toolbarcust)     0        ;# customizable toolbar
  673. set appvals(fieldAdjustment)    0.90        ;# adjustment for string lengths
  674.                          # for drawn list in graphical
  675. proc UiDefaultFormSpacingSet {form} {
  676.     VtSetValues $form \
  677.         -horizontalSpacing 0 \
  678.         -verticalSpacing 0 \
  679.         -marginWidth 0 \
  680.         -marginHeight 0 
  681. }
  682. proc UiDisplayErrorStackCB {callback cbs} {
  683.     global appvals
  684.     set dialog [keylget cbs dialog]
  685.     VtDestroyDialog $dialog
  686.     SaStatusBarClear [VxGetVar $appvals(vtMain) statusBar]
  687.     if {![lempty $callback]} {
  688.         eval $callback [list $cbs]
  689.     }
  690. }
  691. proc UiDisplayErrorStacks {caller stack {callback ""}} {
  692.     global appvals
  693.     SaDisplayErrorStacks $appvals(vtMain).$caller [list $stack] HELP \
  694.         [list UiDisplayErrorStackCB $callback]
  695. }
  696. proc UiSetAppFocus {} {
  697.     global appvals
  698.     VtSetFocus [VxGetVar $appvals(vtMain) menuBar] 
  699.     if {![lempty [UiMainListGetItems]]} {
  700.         VtSetFocus [VxGetVar $appvals(vtMain) mainList]
  701.     }
  702. }
  703. proc AdjustFieldLength {charLength} {
  704.     global appvals
  705.     set fieldLength [expr $charLength * $appvals(fieldAdjustment)]
  706.     return $fieldLength
  707. }
  708. proc UiMainListSetItems {items} {
  709.     global appvals
  710.     set mainList [VxGetVar $appvals(vtMain) mainList]
  711.     VtDrawnListDeleteItem $mainList -all
  712.     set maxLength [VxGetVar $mainList maxLength]
  713.     DomainSetMainListLabel $maxLength
  714.     set isCharm [VtInfo -charm]
  715.     set CHARM_formatList [list  \
  716.         [list STRING 1 1 1] \
  717.         [list STRING $maxLength 1 1]]
  718.     set MOTIF_formatList [list  \
  719.         [list STRING 1 10 10] \
  720.         [list STRING [AdjustFieldLength $maxLength] 0 10]]
  721.     foreach entry $items {
  722.         keylget entry partial partial
  723.         keylget entry hostName hostName
  724.         keylget entry realName realName
  725.         keylget entry route route
  726.         # set up the first two columns in this list item--
  727.         # these are always there: 
  728.         #    indicator of partial domain matching
  729.         #    hostname (key of domain table entry)
  730.         if {$partial == "TRUE"} {
  731.             if {$isCharm} {
  732.                 set partial [IntlMsg COLUMN_PARTIAL_LBL_CHARM]
  733.             } else {
  734.                 set partial [IntlMsg COLUMN_PARTIAL_LBL]
  735.             }
  736.         } else {
  737.             set partial [IntlMsg COLUMN_PARTIAL_NONE]
  738.         }
  739.         set fieldList [list $partial $hostName]
  740.         if {$isCharm} {
  741.             set formatList $CHARM_formatList
  742.         } else {
  743.             set formatList $MOTIF_formatList
  744.         }
  745.         # for each hop in the route (except final),
  746.         # add the string, then the arrow icon
  747.         set routeString ""
  748.         foreach hop $route {
  749.             append routeString "$hop > "
  750.         }
  751.         # add on the final hop in route
  752.         append routeString "$realName"
  753.         lappend fieldList $routeString
  754.         lappend formatList [list \
  755.                 STRING \
  756.                 [AdjustFieldLength [clength $routeString]]]
  757.         lappend formatList [list DATA]
  758.         lappend fieldList $entry
  759.         VtDrawnListAddItem $mainList \
  760.             -formatList $formatList \
  761.             -fieldList $fieldList
  762.     }
  763. }
  764. proc UiMainListGetItems {} {
  765.     global appvals
  766.     return [VtDrawnListGetItem [VxGetVar $appvals(vtMain) mainList] -all]
  767. }
  768. proc UiMainListCB {cbs} {
  769.     global appvals
  770.     # update selected label and widget sensitivity
  771.     UiUpdateCountLabel
  772.     UiSensitizeMainFunctions
  773. }
  774. proc UiMainListDoubleCB {cbs} {
  775.     UiModifyEntryCB $cbs
  776.     VtUnLock
  777. }
  778. proc UiBuildMainList {form top} {
  779.     global appvals 
  780.     # Build basic main form drawnlist widget including:
  781.     # o Manually built title label for CHARM
  782.     # o Drawnlist record format
  783.     # o traditional Count label beneath the drawn list
  784.     set labelFont medNormalFont
  785.     set mainList [DomainBuildMainList $form $top]
  786.     VxSetVar $form mainList $mainList
  787.     set labelForm [VtForm $form.labelForm \
  788.         -topSide NONE \
  789.         -leftSide FORM \
  790.         -rightSide FORM \
  791.         -bottomSide FORM]
  792.         # Define the partial lookup info label
  793.     if {[VtInfo -charm]} {
  794.         set label [IntlMsg PARTIAL_LABEL_STR_CHARM] 
  795.     } else {
  796.         set label [IntlMsg PARTIAL_LABEL_STR] 
  797.     }
  798.     set partialLabel [VtLabel $labelForm.partialLabel \
  799.         -label $label \
  800.         -font smallNormalFont \
  801.         -topSide FORM \
  802.         -topOffset 0 \
  803.         -leftSide FORM \
  804.         -MOTIF_leftOffset 5 -CHARM_leftOffset 0 \
  805.         -rightSide NONE \
  806.         -bottomSide FORM \
  807.         -labelLeft]
  808.     VxSetVar $form partialLabel $partialLabel
  809.     # Define the accompanying count label
  810.     set countLabel [VtLabel $labelForm.countLabel -label " " \
  811.                 -topSide FORM \
  812.                 -leftSide $partialLabel \
  813.                 -rightSide FORM \
  814.                 -bottomSide FORM \
  815.                 -labelRight]
  816.     VxSetVar $form countLabel $countLabel
  817.     VtSetValues $mainList -bottomSide $labelForm
  818.     # Stash the localized string "Selected" here so we only grab it once
  819.     # from the message catalog
  820.     VxSetVar $countLabel selected [IntlMsg SELECTED]
  821.     # Return the bottom-most widget for further attachments
  822.     return $labelForm
  823. }
  824. proc UiUpdateCountLabel {} {
  825.     global appvals
  826.     set mainList [VxGetVar $appvals(vtMain) mainList]
  827.     set countLabel [VxGetVar $appvals(vtMain) countLabel]
  828.     set numSelected [llength \
  829.         [VtDrawnListGetSelectedItem $mainList -byRecordList]]
  830.         lappend labelArgs [llength [VtDrawnListGetItem $mainList -all]]
  831.         lappend labelArgs $appvals(itemname)
  832.         lappend labelArgs $numSelected
  833.         lappend labelArgs [VxGetVar $countLabel selected]
  834.         set labelValue [IntlMsg COUNT_LABEL_STR $labelArgs]
  835.     VtSetValues $countLabel -label $labelValue
  836. }
  837. proc UiBuildAddModifyScreen {} {
  838.     global appvals
  839.     set isCharm [VtInfo -charm]
  840.     set parent $appvals(vtMain)
  841.     set addModifyScreen [VtFormDialog $parent.addModifyScreen \
  842.         -ok -okLabel [IntlMsg OK] \
  843.         -cancel -cancelLabel [IntlMsg CANCEL] \
  844.         -help -helpLabel [IntlMsg HELP] \
  845.         -cancelButton CANCEL \
  846.         -okCallback AddModifyOkCB \
  847.         -cancelCallback AddModifyCancelCB \
  848.         -wmCloseCallback AddModifyCancelCB \
  849.         -autoLock [list AddModifyOkCB AddModifyCancelCB] \
  850.         -resizable FALSE]
  851.     VxSetVar $parent addModifyScreen $addModifyScreen
  852.     UiDefaultFormSpacingSet $addModifyScreen
  853.     SaCharmSetMaxFormDimensions $addModifyScreen 1
  854.     set nameForm [VtForm $addModifyScreen.nameForm \
  855.         -leftSide FORM -MOTIF_leftOffset 0 -CHARM_leftOffset 1 \
  856.         -rightSide FORM -MOTIF_rightOffset 0 -CHARM_rightOffset 1\
  857.         -topSide FORM -MOTIF_topOffset 10 -CHARM_topOffset 1]
  858.     set nameLabel [VtLabel $nameForm.nameLabel \
  859.         -label [IntlMsg NAME_LBL] \
  860.         -labelLeft ]
  861.     set nameText [VtText $nameForm.nameText \
  862.         -leftSide FORM -rightSide FORM \
  863.         -shortHelpCallback SaShortHelpCB \
  864.         -shortHelpString [IntlMsg NAME_SH] \
  865.         -callback {SaSetFocus next}]
  866.     VxSetVar $addModifyScreen nameText $nameText
  867.     set realNameForm [VtForm $addModifyScreen.realNameForm \
  868.         -leftSide FORM -MOTIF_leftOffset 0 -CHARM_leftOffset 1 \
  869.         -rightSide FORM -MOTIF_rightOffset 0 -CHARM_rightOffset 1\
  870.         -topSide $nameForm -MOTIF_topOffset 0 -CHARM_topOffset 1]
  871.     set realNameLabel [VtLabel $realNameForm.realNameLabel \
  872.         -label [IntlMsg REAL_NAME_LBL] \
  873.         -labelLeft ]
  874.     set realNameText [VtText $realNameForm.realNameText \
  875.         -leftSide FORM -rightSide FORM \
  876.         -shortHelpCallback SaShortHelpCB \
  877.         -shortHelpString [IntlMsg REAL_NAME_SH] \
  878.         -callback {SaSetFocus next}]
  879.     VxSetVar $addModifyScreen realNameText $realNameText
  880.     set routeForm [VtForm $addModifyScreen.routeForm \
  881.         -leftSide FORM -alignLeft $realNameForm\
  882.         -rightSide FORM \
  883.         -topSide $realNameForm \
  884.         -bottomSide NONE \
  885.         -MOTIF_topOffset 10 -CHARM_topOffset 1]
  886.     set labelList [list [IntlMsg ROUTE_LIST_LBL]]
  887.     if {$isCharm} {
  888.         set labelFormat "%s"
  889.         set label [format $labelFormat [lindex $labelList 0]]
  890.         set routeLabel [VtLabel $routeForm.routeLabel \
  891.             -labelLeft \
  892.             -leftSide FORM \
  893.             -leftOffset 0 \
  894.             -rightSide FORM \
  895.             -topSide FORM \
  896.             -bottomSide NONE \
  897.             -label $label]
  898.     }
  899.     set routeList [VtDrawnList $routeForm.routeList \
  900.         -labelFormatList {{STRING 20}} \
  901.         -labelList $labelList \
  902.         -formatList {{STRING 20}} \
  903.         -columns 25 -CHARM_columns 35 \
  904.         -rows 6 \
  905.         -topSide FORM -bottomSide NONE \
  906.         -leftSide FORM -rightSide FORM\
  907.         -horizontalScrollBar TRUE \
  908.         -selection MULTIPLE \
  909.         -callback RouteListCB]
  910.     VxSetVar $addModifyScreen routeList $routeList
  911.     if {$isCharm} {
  912.         VtSetValues $routeList -topSide $routeLabel
  913.     }
  914.     set buttonForm [VtForm $routeForm.buttonForm \
  915.         -leftSide NONE -rightSide FORM \
  916.         -MOTIF_rightOffset 0 -CHARM_rightOffset 1 \
  917.         -topSide FORM -bottomSide NONE \
  918.         -MOTIF_topOffset 15 -CHARM_topOffset 1]
  919.     VtSetValues $routeList -rightSide $buttonForm
  920.     set pbRowCol1 [VtRowColumn $buttonForm.pbForm1 \
  921.         -topSide FORM -bottomSide NONE \
  922.         -leftSide FORM -rightSide FORM \
  923.         -vertical]
  924.     set routeAddButton [VtPushButton $pbRowCol1.routeAddButton \
  925.         -label [IntlMsg ROUTE_ADD_BTN_LBL] \
  926.         -labelCenter \
  927.         -shortHelpCallback SaShortHelpCB \
  928.         -shortHelpString \
  929.             [IntlMsg ROUTE_ADD_BTN_SH] \
  930.         -callback AddToRouteCB \
  931.         -autoLock AddToRouteCB ]
  932.     VxSetVar $addModifyScreen routeAddButton $routeAddButton
  933.     set routeDeleteButton [VtPushButton $pbRowCol1.routeDeleteButton \
  934.         -label [IntlMsg ROUTE_DELETE_BTN_LBL] \
  935.         -labelCenter \
  936.         -shortHelpCallback SaShortHelpCB \
  937.         -shortHelpString \
  938.             [IntlMsg ROUTE_DELETE_BTN_SH] \
  939.         -callback DeleteFromRouteCB \
  940.         -autoLock DeleteFromRouteCB ]
  941.     VxSetVar $addModifyScreen routeDeleteButton $routeDeleteButton
  942.     set pbRowCol2 [VtRowColumn $buttonForm.pbRowCol2 \
  943.         -topSide $pbRowCol1 -topOffset 0 -bottomSide NONE \
  944.         -leftSide FORM -rightSide FORM \
  945.         -horizontal \
  946.         -MOTIF_spacing 5 -CHARM_spacing 1 \
  947.         -packing COLUMN]
  948.     set routeMoveUpButton [VtPushButton $pbRowCol2.routeMoveUpButton \
  949.         -shortHelpCallback SaShortHelpCB \
  950.         -shortHelpString \
  951.             [IntlMsg ROUTE_UP_BTN_SH] \
  952.         -callback MoveUpRouteCB \
  953.         -autoLock MoveUpRouteCB ]
  954.     if {$isCharm} {
  955.         VtSetValues $routeMoveUpButton \
  956.             -label " [IntlMsg ENTRY_MENU_UP_LBL] " \
  957.             -labelCenter
  958.     } else {
  959.         VtSetValues $routeMoveUpButton \
  960.             -pixmap [IntlMsg BTN_UP_PX]
  961.     }
  962.     VxSetVar $addModifyScreen routeMoveUpButton $routeMoveUpButton
  963.     set routeMoveDownButton [VtPushButton $pbRowCol2.routeMoveDownButton \
  964.         -shortHelpCallback SaShortHelpCB \
  965.         -shortHelpString \
  966.             [IntlMsg ROUTE_DOWN_BTN_SH] \
  967.         -callback MoveDownRouteCB \
  968.         -autoLock MoveDownRouteCB ]
  969.     if {$isCharm} {
  970.         VtSetValues $routeMoveDownButton \
  971.             -label " [IntlMsg ENTRY_MENU_DOWN_LBL] " \
  972.             -labelCenter
  973.     } else {
  974.         VtSetValues $routeMoveDownButton \
  975.             -pixmap [IntlMsg BTN_DOWN_PX]
  976.     }
  977.     VxSetVar $addModifyScreen routeMoveDownButton $routeMoveDownButton
  978.     set optionsCheckBox [VtCheckBox $routeForm.optionsCheckBox \
  979.         -topSide NONE -bottomSide FORM \
  980.         -leftSide FORM -MOTIF_leftOffset 5 -CHARM_leftOffset 0]
  981.     set doPartial [VtToggleButton $optionsCheckBox.doPartial \
  982.         -label [IntlMsg DO_PARTIAL_LBL] \
  983.         -set FALSE \
  984.         -shortHelpCallback SaShortHelpCB \
  985.         -shortHelpString [IntlMsg DO_PARTIAL_SH] \
  986.         -callback {SaSetFocus next}]
  987.     VxSetVar $addModifyScreen doPartial $doPartial
  988.     set separator [VtSeparator $addModifyScreen.separator \
  989.         -leftSide FORM -leftOffset 0 \
  990.         -rightSide FORM -rightOffset 0 \
  991.         -topSide NONE]
  992.     set statusBar [SaStatusBar $addModifyScreen.statusbar 0]
  993.     VtSetValues $separator \
  994.         -bottomSide $statusBar -bottomOffset 0
  995.     VtSetValues $routeList \
  996.         -bottomSide $optionsCheckBox
  997.     VtSetValues $routeForm \
  998.         -bottomSide $separator
  999.     SaSetTabGroups $buttonForm [list $pbRowCol1 $pbRowCol2]
  1000.     SaSetTabGroups $addModifyScreen [list \
  1001.         $nameText \
  1002.         $realNameText \
  1003.         $routeList \
  1004.         $buttonForm \
  1005.         $doPartial]
  1006.     set okButton [VtGetValues $addModifyScreen -ok]
  1007.     SaSetFocusList $addModifyScreen [list \
  1008.         $nameText \
  1009.         $realNameText \
  1010.         $buttonForm \
  1011.         $doPartial \
  1012.         $okButton]
  1013.     return $addModifyScreen
  1014. }
  1015. proc UiBuildAddToRouteScreen {parent} {
  1016.     set addToRouteScreen [VtFormDialog $parent.addToRouteScreen \
  1017.         -title [IntlMsg ROUTE_ADD_DLG_TITLE] \
  1018.         -ok -okLabel [IntlMsg OK] \
  1019.         -okCallback AddToRouteOkCB \
  1020.         -cancel -cancelLabel [IntlMsg CANCEL] \
  1021.         -cancelCallback AddToRouteCancelCB \
  1022.         -cancelButton CANCEL \
  1023.         -wmCloseCallback AddToRouteCancelCB \
  1024.         -autoLock [list AddToRouteOkCB AddToRouteCancelCB] ]
  1025.         VxSetVar $parent addToRouteScreen $addToRouteScreen
  1026.     set hostNameForm [VtForm $addToRouteScreen.hostNameForm \
  1027.         -marginHeight 0 -marginWidth 0 \
  1028.         -rightSide FORM -leftSide FORM \
  1029.         -topSide FORM -topOffset 10 -CHARM_topOffset 1]
  1030.     set hostNameLabel [VtLabel $hostNameForm.hostNameLabel \
  1031.         -label [IntlMsg ROUTE_ADD_DLG_TEXT_LBL] \
  1032.         -labelLeft ]
  1033.     set selectHostButton [VtPushButton $hostNameForm.selectHostButton \
  1034.         -label [IntlMsg ROUTE_ADD_DLG_BTN_LBL] \
  1035.         -leftSide NONE -rightSide FORM \
  1036.         -bottomSide FORM -MOTIF_bottomOffset 20 -CHARM_bottomOffset 0 \
  1037.         -callback SelectHostCB \
  1038.         -autoLock SelectHostCB]
  1039.         VxSetVar $addToRouteScreen selectHostButton $selectHostButton
  1040.     set hostNameText [VtText $hostNameForm.hostNameText \
  1041.         -columns 30  -CHARM_columns 35 \
  1042.         -leftSide FORM -rightSide $selectHostButton \
  1043.         -alignTop $selectHostButton \
  1044.         -horizontalScrollBar TRUE \
  1045.         -callback EnterHostNameCB \
  1046.         -autoLock EnterHostNameCB ]
  1047.         VxSetVar $addToRouteScreen hostNameText $hostNameText
  1048.     VtAddTabGroup $hostNameText
  1049.     VtAddTabGroup $selectHostButton
  1050.     return $addToRouteScreen
  1051. }
  1052. proc UiRouteListSetItems {items} {
  1053.     global appvals
  1054.     set addModifyScreen [VxGetVar $appvals(vtMain) addModifyScreen] 
  1055.     set routeList [VxGetVar $addModifyScreen routeList]
  1056.     VtDrawnListDeleteItem $routeList -all
  1057.     foreach entry $items {
  1058.         set fieldList [list $entry]
  1059.         set formatList [list [list STRING [clength $entry]]]
  1060.         VtDrawnListAddItem $routeList \
  1061.             -formatList $formatList \
  1062.             -fieldList $fieldList
  1063.     }
  1064. }
  1065. proc UiBuildSaveConfirmDialog {} {
  1066.     global appvals
  1067.     set parent $appvals(vtMain)
  1068.     # we don't do autoDestroy on this dialog, because we
  1069.     # want wmCloseCallback to do the cancel, and the dialog
  1070.     # cannot auto destroy in that case
  1071.     set saveConfirmDlg [VtQuestionDialog $parent.saveConfirmDlg \
  1072.         -title [IntlMsg SAVE_CONFIRM_TITLE] \
  1073.         -message [IntlMsg SAVE_CONFIRM_QUERY] \
  1074.         -autoDestroy FALSE \
  1075.         -okLabel [IntlMsg SAVE_CONFIRM_BTN_YES] \
  1076.         -ok -okCallback SaveConfirmOkCB \
  1077.         -applyLabel [IntlMsg SAVE_CONFIRM_BTN_NO] \
  1078.         -apply -applyCallback SaveConfirmNoCB \
  1079.         -cancelLabel [IntlMsg SAVE_CONFIRM_BTN_CANCEL] \
  1080.         -cancel -cancelCallback SaveConfirmCancelCB \
  1081.         -wmCloseCallback SaveConfirmCancelCB \
  1082.         -autoLock [list \
  1083.             SaveConfirmOkCB SaveConfirmNoCB SaveConfirmCancelCB]]
  1084.     VxSetVar $parent saveConfirm $saveConfirmDlg
  1085.     return $saveConfirmDlg
  1086. }
  1087. proc UiCloseCB {cbs} {
  1088.     # Call underlying non-ui module: close that may need additional ui
  1089.     if {[DomainIsModified]} {
  1090.         CloseWithUi
  1091.         VtUnLock
  1092.         return
  1093.     }
  1094.     UiStop    UiCloseCB2
  1095. }
  1096. proc UiCloseCB2 {{cbs {}}} {
  1097.     # Call underlying non-ui module: close without Ui
  1098.     CloseAfterUi
  1099. }
  1100. proc UiRefreshCB {{cbs {}}} {
  1101.     global appvals
  1102.     set statusBar [VxGetVar $appvals(vtMain) statusBar]
  1103.     set mainList [VxGetVar $appvals(vtMain) mainList]
  1104.     SaStatusBarSet $statusBar [IntlMsg REFRESH] 
  1105.     Refresh
  1106.     # Update count label and widget sensitivity
  1107.     UiUpdateCountLabel
  1108.     UiSensitizeMainFunctions
  1109.     SaStatusBarClear $statusBar
  1110.     VtUnLock
  1111. }
  1112. proc EnterHostNameCB {cbs} {
  1113.     set dialog [keylget cbs dialog]
  1114.     set widget [keylget cbs widget]
  1115.     set mode [keylget cbs mode]
  1116.     set name [keylget cbs value]
  1117.     if {$mode == "done"} {
  1118.         if {[lempty $name]} {
  1119.             VtShow [VtErrorDialog $dialog.usererr1 \
  1120.                 -message [IntlErr ENTER_NAME] \
  1121.                 -ok]
  1122.             set hostNameText [VxGetVar $dialog hostNameText]
  1123.             VtSetFocus $hostNameText
  1124.             VtUnLock
  1125.             return
  1126.         } else {
  1127.             set okButton [VtGetValues $dialog -ok]
  1128.             VtSetFocus $okButton
  1129.         }
  1130.     }
  1131.     VtUnLock
  1132. }
  1133. proc SelectHostOkCB {addToRouteScreen cbs} {
  1134.     global appvals
  1135.     set dialog [keylget cbs dialog]
  1136.     set instance $appvals(selecthost)
  1137.     set selection [SaSelectHostGetSelection $instance]
  1138.     set hostNameText [VxGetVar $addToRouteScreen hostNameText]
  1139.     set currentVal [VtGetValues $hostNameText -value]
  1140.     lappend currentVal $selection
  1141.     VtSetValues $hostNameText -value $currentVal
  1142.     VtSetValues $hostNameText \
  1143.         -xmArgs [list XmNcursorPosition [string length $currentVal]]
  1144.     VtSetFocus $hostNameText
  1145.     VtUnLock
  1146. }
  1147. proc SelectHostCB {cbs} {
  1148.     global appvals
  1149.     set parent [keylget cbs dialog]
  1150.     keylset parameters parent $parent
  1151.     keylset parameters instance selectHostScreen
  1152.     set appvals(selecthost) selectHostScreen
  1153.     keylset parameters userproc "SelectHostOkCB $parent" 
  1154.     SaSelectHostDialog $parameters $cbs
  1155. }
  1156. proc AddToRouteOkCB {cbs} {
  1157.     set dialog [keylget cbs dialog]
  1158.     set hostNameText [VxGetVar $dialog hostNameText]
  1159.     set route [VtGetValues $hostNameText -value]
  1160.     if {[lempty $route]} {
  1161.         VtShow [VtErrorDialog $dialog.usererr1 \
  1162.             -message [IntlErr ENTER_NAME] \
  1163.             -ok]
  1164.         VtSetFocus $hostNameText
  1165.         VtUnLock
  1166.         return
  1167.     }
  1168.     set addModifyScreen [VxGetVar $dialog parent_dlg]
  1169.     set routeList [VxGetVar $addModifyScreen routeList]
  1170.     set currentItems [VtDrawnListGetItem $routeList -all]
  1171.     set currentSelectedItems [VtDrawnListGetSelectedItem $routeList \
  1172.                     -byPositionList]
  1173.     VtDestroyDialog $dialog
  1174.     if {[lempty $currentItems]} {
  1175.         UiRouteListSetItems $route
  1176.         VtDrawnListSelectItem $routeList -all
  1177.     } else {
  1178.         if {$currentSelectedItems == 0} {
  1179.             UiRouteListSetItems [concat $currentItems $route]
  1180.             set pos [llength $currentItems]
  1181.             set positions {}
  1182.             foreach hop $route {
  1183.                 incr pos
  1184.                 lappend positions $pos
  1185.             }
  1186.             VtDrawnListSelectItem \
  1187.                 $routeList -positionList $positions
  1188.         } else {
  1189.             set pos [lindex $currentSelectedItems end]
  1190.             set firstPositions {}
  1191.             for {set index 1} {$index <= $pos} {incr index} {
  1192.                 lappend firstPositions $index
  1193.             }
  1194.             set lastPositions {}
  1195.             for {set index [expr $pos + 1]} \
  1196.                 {$index <= [llength $currentItems]} {incr index} {
  1197.                 lappend lastPositions $index
  1198.             }
  1199.             set lastNewPosition [expr $pos + [llength $route]]
  1200.             set newPositions {}
  1201.             for {set index [expr $pos + 1]} \
  1202.                 {$index <= $lastNewPosition} {incr index} {
  1203.                 lappend newPositions $index
  1204.             }
  1205.             set begItems [VtDrawnListGetItem $routeList \
  1206.                     -positionList $firstPositions]
  1207.             set lastItems [VtDrawnListGetItem $routeList \
  1208.                     -positionList $lastPositions]
  1209.             UiRouteListSetItems [concat $begItems $route $lastItems]
  1210.             VtDrawnListSelectItem \
  1211.                 $routeList -positionList $newPositions
  1212.         }
  1213.     }
  1214.     SaDrawnListShowSelectedItem $routeList
  1215.     UiSensitizeAddModifyFunctions $addModifyScreen
  1216.     VtUnLock
  1217. }
  1218. proc AddToRouteCancelCB {cbs} {
  1219.     set dialog [keylget cbs dialog]
  1220.     VtDestroyDialog $dialog
  1221.     VtUnLock
  1222.     return
  1223. }
  1224. proc AddToRouteCB {cbs} {
  1225.     set parent [keylget cbs dialog]
  1226.     set mode [keylget cbs mode]
  1227.     set name [keylget cbs value]
  1228.     set addToRouteScreen [UiBuildAddToRouteScreen $parent]
  1229.     VxSetVar $addToRouteScreen parent_dlg $parent
  1230.     set hostNameText [VxGetVar $addToRouteScreen hostNameText]
  1231.     VtShow $addToRouteScreen
  1232.     VtSetFocus $hostNameText
  1233.     VtUnLock
  1234. }
  1235. proc DeleteFromRouteCB {cbs} {
  1236.     set dialog [keylget cbs dialog]
  1237.     set routeList [VxGetVar $dialog routeList]
  1238.     set selectedPositions [VtDrawnListGetSelectedItem \
  1239.                 $routeList -byPositionList]
  1240.     set prevTotal [llength [VtDrawnListGetItem $routeList -all]]
  1241.     VtDrawnListDeleteItem $routeList -positionList $selectedPositions
  1242.     set numItemsLeft [llength [VtDrawnListGetItem $routeList -all]]
  1243.     if {$numItemsLeft > 0} {
  1244.         set first [lindex $selectedPositions 0]
  1245.         set last [lindex $selectedPositions end]
  1246.         set numDeleted [llength $selectedPositions]
  1247.         if {[expr $last - $first + 1] == $numDeleted} {
  1248.             set contiguous 1
  1249.         } else {
  1250.             set contiguous 0
  1251.         }
  1252.         if {$last == $prevTotal && $contiguous} {
  1253.             # select the one above
  1254.              VtDrawnListSelectItem $routeList \
  1255.                 -position [expr $first - 1]
  1256.         } else {
  1257.             # select the item that was after the first deleted
  1258.             # (same position number as first deleted was)
  1259.             VtDrawnListSelectItem $routeList -position $first
  1260.         }
  1261.         SaDrawnListShowSelectedItem $routeList
  1262.     }
  1263.     UiSensitizeAddModifyFunctions $dialog
  1264.     VtUnLock
  1265. }
  1266. proc RouteListCB {cbs} {
  1267.     set dialog [keylget cbs dialog]
  1268.     UiSensitizeAddModifyFunctions $dialog
  1269. }
  1270. proc MoveUpRouteCB {cbs} {
  1271.     set dialog [keylget cbs dialog]
  1272.     set routeList [VxGetVar $dialog routeList]
  1273.     set selectedNum [lindex \
  1274.         [VtDrawnListGetSelectedItem $routeList -byPositionList] 0]
  1275.     if {$selectedNum == 1} {
  1276.         VtBeep
  1277.         VtUnLock
  1278.         return
  1279.     }
  1280.     set selectedItem [VtDrawnListGetItem $routeList -position $selectedNum]
  1281.     set newPosition [expr $selectedNum - 1]
  1282.     VtDrawnListDeleteItem $routeList -position $selectedNum
  1283.     VtDrawnListAddItem $routeList -position $newPosition \
  1284.                       -formatList [list [list STRING 25]] \
  1285.                       -fieldList $selectedItem
  1286.     VtDrawnListSelectItem $routeList -position $newPosition
  1287.     SaDrawnListShowSelectedItem $routeList
  1288.     VtUnLock
  1289.     return
  1290. }
  1291. proc MoveDownRouteCB {cbs} {
  1292.     set dialog [keylget cbs dialog]
  1293.     set routeList [VxGetVar $dialog routeList]
  1294.     set selectedNum [lindex \
  1295.         [VtDrawnListGetSelectedItem $routeList -byPositionList] 0]
  1296.     set totalNum [llength [VtDrawnListGetItem $routeList -all]]
  1297.     if {$selectedNum == $totalNum} {
  1298.         VtBeep
  1299.         VtUnLock
  1300.         return
  1301.     }
  1302.     set selectedItem [VtDrawnListGetItem $routeList -position $selectedNum]
  1303.     set newPosition [expr $selectedNum + 1]
  1304.     VtDrawnListDeleteItem $routeList -position $selectedNum
  1305.     VtDrawnListAddItem $routeList -position $newPosition \
  1306.                       -formatList [list [list STRING 25]] \
  1307.                       -fieldList [list $selectedItem]
  1308.     VtDrawnListSelectItem $routeList -position $newPosition
  1309.     SaDrawnListShowSelectedItem $routeList
  1310.     VtUnLock
  1311.     return
  1312. }
  1313. proc AddModifyCancelCB {cbs} {
  1314.     set dialog [keylget cbs dialog]
  1315.     VtDestroyDialog $dialog
  1316.     VtUnLock
  1317.     return
  1318. }
  1319. proc AddModifyOkCB {cbs} {
  1320.     global appvals
  1321.     set dialog [keylget cbs dialog]
  1322.     set function [VxGetVar $dialog function]
  1323.     set nameText [VxGetVar $dialog nameText]
  1324.     set realNameText [VxGetVar $dialog realNameText]
  1325.     set routeList [VxGetVar $dialog routeList]
  1326.     set doPartial [VxGetVar $dialog doPartial]
  1327.     # get the values entered into the widgets
  1328.     set newHostName [string trim [VtGetValues $nameText -value]]
  1329.     set newRealName [string trim [VtGetValues $realNameText -value]]
  1330.     set newRoute [VtDrawnListGetItem $routeList -all]
  1331.     set newPartial [VtGetValues $doPartial -value]
  1332.     if {[clength $newHostName] == 0 || [ctype space $newHostName]} {
  1333.         VtShow [VtErrorDialog $dialog.usererr1 \
  1334.             -message [IntlErr NAME_MISSING] \
  1335.             -ok]
  1336.         VtUnLock
  1337.         VtSetFocus $nameText
  1338.         return
  1339.     }
  1340.     if {[regexp {[     ]} $newHostName]} { 
  1341.         VtShow [VtErrorDialog $dialog.usererr2 \
  1342.             -message [IntlErr NAME_SPACE] \
  1343.             -ok]
  1344.         VtUnLock
  1345.         VtSetFocus $nameText
  1346.         return
  1347.     }
  1348.     if {[clength $newRealName] == 0 || [ctype space $newRealName]} {
  1349.         VtShow [VtErrorDialog $dialog.usererr3 \
  1350.             -message [IntlErr REAL_NAME_MISSING] \
  1351.             -ok]
  1352.         VtUnLock
  1353.         VtSetFocus $realNameText
  1354.         return
  1355.     }
  1356.     if {[regexp {[     ]} $newRealName]} { 
  1357.         VtShow [VtErrorDialog $dialog.usererr4 \
  1358.             -message [IntlErr NAME_SPACE] \
  1359.             -ok]
  1360.         VtUnLock
  1361.         VtSetFocus $realNameText
  1362.         return
  1363.     }
  1364.     # Don't allow partial lookups on numeric addresses
  1365.     if {[regexp {\[[0-9\.]+\]} $newHostName] && $newPartial} {
  1366.         VtShow [VtErrorDialog $dialog.usererr5 \
  1367.             -message [IntlErr NUMERIC] \
  1368.             -ok]
  1369.         VtUnLock
  1370.         VtSetFocus $doPartial
  1371.         return
  1372.     }
  1373.     # set up the new entry
  1374.     if {$newPartial} {
  1375.         set newPartial TRUE
  1376.         keylset newEntry partial $newPartial
  1377.     } else {
  1378.         set newPartial FALSE
  1379.         keylset newEntry partial $newPartial
  1380.     }
  1381.     keylset newEntry hostName $newHostName
  1382.     keylset newEntry realName $newRealName
  1383.     keylset newEntry route $newRoute
  1384.     set mainList [VxGetVar $appvals(vtMain) mainList]
  1385.     set selected [VtDrawnListGetSelectedItem $mainList -byRecordList]
  1386.     if {$function == "add"} {
  1387.         if {[DomainEntryExists $newHostName]} {
  1388.             VtShow [VtErrorDialog $dialog.usererr5 \
  1389.                 -message [IntlErr NAME_DUPLICATE $newHostName] \
  1390.                 -ok]
  1391.             VtUnLock
  1392.             VtSetFocus $nameText
  1393.             return
  1394.         }
  1395.         if {[lempty $selected]} {
  1396.             # just put the new entry last
  1397.             set position 0
  1398.             set before [lindex [VtDrawnListGetItem $mainList \
  1399.                         -position 0] 0]
  1400.         } else {
  1401.             # put the new entry after the last selected entry
  1402.             set selectedNum [lindex [VtDrawnListGetSelectedItem \
  1403.                         $mainList -byPositionList] end]
  1404.             set position [expr $selectedNum + 1] 
  1405.             set before [lindex $selected end]
  1406.         }
  1407.         if {[cequal $before ""]} {
  1408.             set beforeEntry ""
  1409.         } else {
  1410.             set beforeEntry [lindex $before end]
  1411.         }
  1412.         # update the data structures
  1413.         DomainAdd $beforeEntry $newEntry
  1414.     } else {
  1415.         set position [lindex [VtDrawnListGetSelectedItem $mainList \
  1416.                     -byPositionList] 0]
  1417.         set oldEntry [lindex [lindex $selected 0] end]
  1418.         set oldPartial ""
  1419.         keylget oldEntry partial oldPartial 
  1420.         set oldHostName ""
  1421.         keylget oldEntry hostName oldHostName 
  1422.         set oldRealName ""
  1423.         keylget oldEntry realName oldRealName 
  1424.         set oldRoute ""
  1425.         keylget oldEntry route oldRoute 
  1426.         if {![cequal [string tolower $newHostName] \
  1427.                  [string tolower $oldHostName]] && \
  1428.             [DomainEntryExists $newHostName]} {
  1429.             VtShow [VtErrorDialog $dialog.usererr6 \
  1430.                 -message [IntlErr NAME_DUPLICATE $newHostName] \
  1431.                 -ok]
  1432.             VtUnLock
  1433.             VtSetFocus $nameText
  1434.             return
  1435.         }
  1436.         set modified 0
  1437.         if {$newPartial != $oldPartial || \
  1438.             $newHostName != $oldHostName || \
  1439.             $newRealName != $oldRealName || \
  1440.             $newRoute != $oldRoute} {
  1441.             DomainModify $oldEntry $newEntry
  1442.             set modified 1
  1443.         }
  1444.     }
  1445.     VtDestroyDialog $dialog
  1446.     # update the main drawn list
  1447.     if {$function == "add" || ($function == "modify" && $modified)} {
  1448.         set maxLength [VxGetVar $mainList maxLength]
  1449.         set newLength [clength $newHostName]
  1450.         if {$newLength < $maxLength} {
  1451.             set newLength $maxLength
  1452.         }
  1453.         # For now, we punt on re-drawing the list if the new
  1454.         # host length is larger than the known max length --
  1455.         # this is an expensive operation.
  1456.         set isCharm [VtInfo -charm]
  1457.         if {$isCharm} {
  1458.             set formatList [list \
  1459.                 [list STRING 1 1 1] \
  1460.                 [list STRING $newLength 1 1] ]
  1461.         } else {
  1462.             set formatList [list \
  1463.                 [list STRING 1 10 10] \
  1464.                 [list STRING [AdjustFieldLength $newLength] 0 10]]
  1465.         }
  1466.         if {$newPartial == "TRUE"} {
  1467.             if {[VtInfo -charm]} {
  1468.                 set fieldList [list \
  1469.                     [IntlMsg COLUMN_PARTIAL_LBL_CHARM]]
  1470.             } else {
  1471.                 set fieldList [list \
  1472.                     [IntlMsg COLUMN_PARTIAL_LBL]]
  1473.             }
  1474.         } else {
  1475.             set fieldList \
  1476.                 [list [IntlMsg COLUMN_PARTIAL_NONE]]
  1477.         }
  1478.         lappend fieldList $newHostName
  1479.         set routeString ""
  1480.         foreach hop $newRoute {
  1481.             append routeString "$hop > "
  1482.         }
  1483.         append routeString $newRealName
  1484.         lappend fieldList $routeString
  1485.         lappend formatList [list \
  1486.                 STRING \
  1487.                 [AdjustFieldLength [clength $routeString]]]
  1488.         lappend fieldList $newEntry
  1489.         lappend formatList [list DATA]
  1490.         if {$function == "modify"} {
  1491.             VtDrawnListDeleteItem $mainList -position $position
  1492.         }
  1493.         VtDrawnListAddItem $mainList -formatList $formatList \
  1494.                          -fieldList $fieldList \
  1495.                          -position $position
  1496.         VtDrawnListSelectItem $mainList -position $position
  1497.         SaDrawnListShowSelectedItem $mainList
  1498.         UiSensitizeMainFunctions
  1499.         if {"$function" == "add"} {
  1500.             UiUpdateCountLabel
  1501.         }
  1502.     }
  1503.     VtUnLock
  1504.     return
  1505. }
  1506. proc UiAddEntryCB {cbs} {
  1507.     set addScreen [UiBuildAddModifyScreen]
  1508.     VxSetVar $addScreen function add
  1509.     set nameText [VxGetVar $addScreen nameText]
  1510.     set addButton [VxGetVar $addScreen routeAddButton]
  1511.     set deleteButton [VxGetVar $addScreen routeDeleteButton]
  1512.     set upButton [VxGetVar $addScreen routeMoveUpButton]
  1513.     set downButton [VxGetVar $addScreen routeMoveDownButton]
  1514.     VtSetValues $addScreen -title [IntlMsg ADD_TITLE]
  1515.     VtSetSensitive $addButton 1
  1516.     VtSetSensitive $deleteButton 0
  1517.     VtSetSensitive $upButton 0
  1518.     VtSetSensitive $downButton 0
  1519.     VtShow $addScreen
  1520.     VtSetFocus $nameText
  1521.     VtUnLock
  1522. }
  1523. proc UiDeleteEntryCB {cbs} {
  1524.     global appvals
  1525.     set list [VxGetVar $appvals(vtMain) mainList]
  1526.     set selectedPositions [VtDrawnListGetSelectedItem $list -byPositionList]
  1527.     set prevTotal [llength [VtDrawnListGetItem $list -all]]
  1528.     set deleteEntries {}
  1529.     foreach item [VtDrawnListGetSelectedItem $list -byRecordList] {
  1530.         lappend deleteEntries [lindex $item end]
  1531.     }
  1532.     DomainDelete $deleteEntries
  1533.     VtDrawnListDeleteItem $list -positionList $selectedPositions
  1534.     set numItemsLeft [llength [VtDrawnListGetItem $list -all]]
  1535.     if {$numItemsLeft > 0} {
  1536.         set first [lindex $selectedPositions 0]
  1537.         set last [lindex $selectedPositions end]
  1538.         set numDeleted [llength $selectedPositions]
  1539.         if {[expr $last - $first + 1] == $numDeleted} {
  1540.             set contiguous 1
  1541.         } else {
  1542.             set contiguous 0
  1543.         }
  1544.         if {$last == $prevTotal && $contiguous} {
  1545.             # select the one above
  1546.             VtDrawnListSelectItem $list -position [expr $first - 1]
  1547.         } else {
  1548.             # select the item that was after the first deleted
  1549.             # (same position number as first deleted was)
  1550.             VtDrawnListSelectItem $list -position $first
  1551.         }
  1552.         SaDrawnListShowSelectedItem $list
  1553.     }
  1554.     UiSensitizeMainFunctions
  1555.     UiUpdateCountLabel
  1556.     VtUnLock
  1557. }
  1558. proc UiModifyEntryCB {cbs} {
  1559.     set dialog [keylget cbs dialog] 
  1560.     set mainList [VxGetVar $dialog mainList]
  1561.     set selected [lindex \
  1562.         [VtDrawnListGetSelectedItem $mainList -byItemList] 0]
  1563.     set modifyScreen [UiBuildAddModifyScreen]
  1564.     VxSetVar $modifyScreen function modify
  1565.     set nameText [VxGetVar $modifyScreen nameText]
  1566.     set realNameText [VxGetVar $modifyScreen realNameText]
  1567.     set routeList [VxGetVar $modifyScreen routeList]
  1568.     set doPartial [VxGetVar $modifyScreen doPartial]
  1569.     set addButton [VxGetVar $modifyScreen routeAddButton]
  1570.     set deleteButton [VxGetVar $modifyScreen routeDeleteButton]
  1571.     set upButton [VxGetVar $modifyScreen routeMoveUpButton]
  1572.     set downButton [VxGetVar $modifyScreen routeMoveDownButton]
  1573.     set modifyEntry [lindex $selected end]
  1574.     set partial ""
  1575.     keylget modifyEntry partial partial
  1576.     set hostName ""
  1577.     keylget modifyEntry hostName hostName
  1578.     set realName ""
  1579.     keylget modifyEntry realName realName
  1580.     set route ""
  1581.     keylget modifyEntry route route
  1582.     VtSetValues $modifyScreen -title [IntlMsg MODIFY_TITLE]
  1583.     VtSetValues $doPartial -set $partial
  1584.     VtSetValues $nameText -value $hostName
  1585.     VtSetValues $realNameText -value $realName
  1586.     foreach hop $route {
  1587.         VtDrawnListAddItem $routeList  \
  1588.             -fieldList [list $hop] \
  1589.             -formatList [list [list STRING 25]]
  1590.     }
  1591.     if {[lempty $route]} {
  1592.         VtSetSensitive $addButton 1
  1593.         VtSetSensitive $deleteButton 0
  1594.         VtSetSensitive $upButton 0
  1595.         VtSetSensitive $downButton 0
  1596.     } else {
  1597.         VtSetSensitive $addButton 1
  1598.         VtSetSensitive $deleteButton 1
  1599.         VtSetSensitive $upButton 1
  1600.         VtSetSensitive $downButton 1
  1601.         VtDrawnListSelectItem $routeList -position 1
  1602.     }
  1603.     VtShow $modifyScreen
  1604.     VtSetFocus $nameText
  1605.     VtUnLock
  1606. }
  1607. proc UiMoveUpEntryCB {cbs} {
  1608.     global appvals
  1609.     set list [VxGetVar $appvals(vtMain) mainList]
  1610.     set selectedNum [lindex \
  1611.         [VtDrawnListGetSelectedItem $list -byPositionList] 0]
  1612.     if {$selectedNum == 1} {
  1613.         VtBeep
  1614.         VtUnLock
  1615.         return
  1616.     }
  1617.     set selectedItem [lindex \
  1618.         [VtDrawnListGetItem $list -position $selectedNum] 0]
  1619.     set newPosition [expr $selectedNum - 1]
  1620.     set beforeItem [lindex \
  1621.         [VtDrawnListGetItem $list -position $newPosition] 0]
  1622.     #
  1623.     # Update table data structures
  1624.     #
  1625.     set entry1 [lindex $beforeItem end]
  1626.     set entry2 [lindex $selectedItem end]
  1627.     DomainSwapPosition $entry1 $entry2
  1628.     #
  1629.     # Modify main list widget
  1630.     #
  1631.     # Delete the item selected in the list
  1632.     VtDrawnListDeleteItem $list -position $selectedNum
  1633.     # Add the deleted item back in the new position
  1634.     set maxLength [VxGetVar $list maxLength]    
  1635.     if {[VtInfo -charm]} {
  1636.         set formatList [list \
  1637.             [list STRING 1 1 1] \
  1638.             [list STRING $maxLength 1 1]]
  1639.         set icon [list ICON 1 1 1]
  1640.     } else {
  1641.         set formatList [list \
  1642.             [list STRING 1 10 10] \
  1643.             [list STRING [AdjustFieldLength $maxLength] 0 10]]
  1644.         set icon [list ICON 1 0 5]
  1645.     }
  1646.     lappend formatList [list STRING [clength [lindex $selectedItem 2]]]
  1647.     VtDrawnListAddItem $list -position $newPosition \
  1648.         -fieldList $selectedItem \
  1649.         -formatList $formatList
  1650.     VtDrawnListSelectItem $list -position $newPosition
  1651.     SaDrawnListShowSelectedItem $list
  1652.     VtUnLock
  1653. }
  1654. proc UiMoveDownEntryCB {cbs} {
  1655.     global appvals
  1656.     set list [VxGetVar $appvals(vtMain) mainList]
  1657.     set selectedNum [lindex \
  1658.         [VtDrawnListGetSelectedItem $list -byPositionList] 0]
  1659.     set numItems [llength [VtDrawnListGetItem $list -all]]
  1660.     if {$selectedNum == $numItems} {
  1661.         VtBeep
  1662.         VtUnLock
  1663.         return
  1664.     }
  1665.     set selectedItem [lindex \
  1666.         [VtDrawnListGetItem $list -position $selectedNum] 0]
  1667.     set newPosition [expr $selectedNum + 1]
  1668.     set afterItem [lindex \
  1669.         [VtDrawnListGetItem $list -position $newPosition] 0]
  1670.     #
  1671.     # Update table data structures
  1672.     #
  1673.     set entry1 [lindex $selectedItem end]
  1674.     set entry2 [lindex $afterItem end]
  1675.     DomainSwapPosition $entry1 $entry2
  1676.     #
  1677.     # Modify main list widget
  1678.     #
  1679.     # Delete the item selected in the list
  1680.     VtDrawnListDeleteItem $list -position $selectedNum
  1681.     # Add the deleted item back in the new position
  1682.     set maxLength [VxGetVar $list maxLength]
  1683.     if {[VtInfo -charm]} {
  1684.         set formatList [list \
  1685.             [list STRING 1 1 1] \
  1686.             [list STRING $maxLength 1 1]]
  1687.         set icon [list ICON 1 1 1]
  1688.     } else {
  1689.         set formatList [list \
  1690.             [list STRING 1 10 10] \
  1691.             [list STRING [AdjustFieldLength $maxLength] 0 10]]
  1692.         set icon [list ICON 1 0 5]
  1693.     }
  1694.     lappend formatList [list STRING [clength [lindex $selectedItem 2]]]
  1695.     VtDrawnListAddItem $list -position $newPosition \
  1696.         -fieldList $selectedItem \
  1697.         -formatList $formatList
  1698.     VtDrawnListSelectItem $list -position $newPosition
  1699.     SaDrawnListShowSelectedItem $list
  1700.     VtUnLock
  1701. }
  1702. proc SaveConfirmOkCB {cbs} {
  1703.     set dialog [keylget cbs dialog]
  1704.     VtDestroyDialog $dialog
  1705.     if {[UiSaveCB {}] != 1} {
  1706.         VtUnLock
  1707.         return
  1708.     } else {
  1709.         VtUnLock
  1710.         UiStop  UiCloseCB2
  1711.     }
  1712. }
  1713. proc SaveConfirmNoCB {cbs} {
  1714.     set dialog [keylget cbs dialog]
  1715.     VtDestroyDialog $dialog
  1716.     VtUnLock
  1717.     UiStop  UiCloseCB2
  1718. }
  1719. proc SaveConfirmCancelCB {cbs} {
  1720.     set dialog [keylget cbs dialog]
  1721.     VtDestroyDialog $dialog
  1722.     VtUnLock
  1723.     return
  1724. }
  1725. proc UiSaveCB {cbs} {
  1726.     global appvals
  1727.     set statusBar [VxGetVar $appvals(vtMain) statusBar]
  1728.     SaStatusBarSet $statusBar [IntlMsg SAVE]
  1729.     if {[ErrorCatch errStack 0 DomainWrite data]} {
  1730.         VtUnLock
  1731.         UiDisplayErrorStacks UiSaveCB $errStack
  1732.         return 0
  1733.     }
  1734.     SaStatusBarClear $statusBar
  1735.     VtUnLock
  1736.     return 1
  1737. }
  1738. proc UiSensitizeMainFunctions {} {
  1739.     # visit all appropriate menu items:
  1740.     #     VxGetVar
  1741.     #    VtSetsensitive
  1742.     global appvals
  1743.     set mainList [VxGetVar $appvals(vtMain) mainList]
  1744.     set item [VtDrawnListGetSelectedItem $mainList]
  1745.     set selected [llength \
  1746.         [VtDrawnListGetSelectedItem $mainList -byRecordList]]
  1747.     set menuBar [VxGetVar $appvals(vtMain) menuBar]
  1748.     set add [VxGetVar $menuBar add]
  1749.     set delete [VxGetVar $menuBar delete]
  1750.     set modify [VxGetVar $menuBar modify]
  1751.     set moveUp [VxGetVar $menuBar moveUp]
  1752.     set moveDown [VxGetVar $menuBar moveDown]
  1753.     set isCharm [VtInfo -charm]
  1754.     if {!$isCharm} {
  1755.         set toolBar [VxGetVar $appvals(vtMain) toolBar]
  1756.         set addTB [VxGetVar $toolBar addTB]
  1757.         set deleteTB [VxGetVar $toolBar deleteTB]
  1758.         set modifyTB [VxGetVar $toolBar modifyTB]
  1759.         set upTB [VxGetVar $toolBar upTB]
  1760.         set downTB [VxGetVar $toolBar downTB]
  1761.     }
  1762.     if {$selected == 0} {
  1763.         VtSetSensitive $delete 0
  1764.         VtSetSensitive $modify 0
  1765.         VtSetSensitive $moveUp 0
  1766.         VtSetSensitive $moveDown 0
  1767.         if {!$isCharm} {
  1768.             VtSetSensitive $deleteTB 0
  1769.             VtSetSensitive $modifyTB 0
  1770.             VtSetSensitive $upTB 0
  1771.             VtSetSensitive $downTB 0
  1772.         }
  1773.     } elseif {$selected == 1} {
  1774.         VtSetSensitive $delete 1
  1775.         VtSetSensitive $modify 1
  1776.         VtSetSensitive $moveUp 1
  1777.         VtSetSensitive $moveDown 1
  1778.         if {!$isCharm} {
  1779.             VtSetSensitive $deleteTB 1
  1780.             VtSetSensitive $modifyTB 1
  1781.             VtSetSensitive $upTB 1
  1782.             VtSetSensitive $downTB 1
  1783.         }
  1784.     } else {
  1785.         VtSetSensitive $delete 1
  1786.         VtSetSensitive $modify 0
  1787.         VtSetSensitive $moveUp 0
  1788.         VtSetSensitive $moveDown 0
  1789.         if {!$isCharm} {
  1790.             VtSetSensitive $deleteTB 1
  1791.             VtSetSensitive $modifyTB 0
  1792.             VtSetSensitive $upTB 0
  1793.             VtSetSensitive $downTB 0
  1794.         }
  1795.     }
  1796. }
  1797. proc UiSensitizeAddModifyFunctions {addModifyScreen} {
  1798.     set deleteButton [VxGetVar $addModifyScreen routeDeleteButton]
  1799.     set upButton [VxGetVar $addModifyScreen routeMoveUpButton]
  1800.     set downButton [VxGetVar $addModifyScreen routeMoveDownButton]
  1801.     set routeList [VxGetVar $addModifyScreen routeList]
  1802.     set selected [llength \
  1803.         [VtDrawnListGetSelectedItem $routeList -byRecordList]]
  1804.     if {$selected == 0} {
  1805.         VtSetSensitive $deleteButton 0
  1806.         VtSetSensitive $upButton 0
  1807.         VtSetSensitive $downButton 0
  1808.     } elseif {$selected == 1} {
  1809.         VtSetSensitive $deleteButton 1
  1810.         VtSetSensitive $upButton 1
  1811.         VtSetSensitive $downButton 1
  1812.     } else {
  1813.         VtSetSensitive $deleteButton 1
  1814.         VtSetSensitive $upButton 0
  1815.         VtSetSensitive $downButton 0
  1816.     }
  1817. }
  1818. proc UiStart {} {
  1819.     global appvals
  1820.     # Open/connect to widget server
  1821.     set vtApp [VtOpen $appvals(client) [IntlMsg HELPBOOK]]
  1822.     set appvals(vtApp) $vtApp
  1823.     VtSetAppValues $vtApp \
  1824.                 -errorCallback {SaUnexpectedErrorCB {}}
  1825.     # Create main dialog
  1826.     set vtMain [VtFormDialog $vtApp.main \
  1827.             -title $appvals(title) \
  1828.             -resizable FALSE \
  1829.             -wmShadowThickness 0 \
  1830.             -wmCloseCallback UiCloseCB] 
  1831.     set appvals(vtMain) $vtMain
  1832.     VxSetVar $appvals(vtMain) vtMain $vtMain
  1833.     UiDefaultFormSpacingSet $vtMain
  1834.     SaCharmSetMaxFormDimensions $vtMain
  1835.     # Build pulldown menus
  1836.     set menuBar [UiBuildMenus $vtMain]
  1837.     VxSetVar $appvals(vtMain) menuBar $menuBar
  1838.     # Build the toolbar
  1839.     if {! [VtInfo -charm]} {
  1840.         set toolBar [UiBuildToolBar $vtMain $menuBar]
  1841.     }
  1842.     # Basic drawnlist for domain table entries
  1843.     # Pass main form and widget just above for attachments
  1844.     if {[VtInfo -charm]} {
  1845.         set mainList [UiBuildMainList $vtMain $menuBar]
  1846.     } else {
  1847.         set mainList [UiBuildMainList $vtMain $toolBar]
  1848.     }
  1849.     # Build the status bar with standard SCOadmin status bar pixmap
  1850.     set statusBar [SaStatusBar $vtMain.statusBar 1]
  1851.     VxSetVar $appvals(vtMain) statusBar $statusBar
  1852.     # Connect main screen widget bottom to statusbar
  1853.     VtSetValues $mainList -bottomSide $statusBar
  1854.     # Display the main form and lock it
  1855.     VtShow $vtMain
  1856.     VtLock
  1857. }
  1858. proc UiStop {cb} {
  1859.     global appvals
  1860.     set vtMain $appvals(vtMain)
  1861.     set client $appvals(client)
  1862.     # Store modified preferences
  1863.     # short help
  1864.     set cmd [list SaShortHelpStore $client]
  1865.     if {[ErrorCatch errorStack 0 $cmd dummy] != 0 } {
  1866.         lappend errorStacks $errorStack
  1867.     }
  1868.     # any problems?
  1869.     if [info exists errorStacks] {
  1870.         # present error dialog and enter event-driven Ui loop.
  1871.         # Re-gain procedural control via UiStop2 (part 2) and
  1872.         # eventuall, the caller's cb
  1873.         SaDisplayErrorStacks $vtMain.UIStop $errorStacks {} \
  1874.             [list UiStop2 $cb]
  1875.         VtUnLock
  1876.         VtMainLoop
  1877.     } else {
  1878.         # stop vtcl
  1879.         VtUnLock
  1880.         VtClose
  1881.         # return control to the caller
  1882.         eval $cb
  1883.     }
  1884. }
  1885. proc UiStop2 {cb {cbs {}}} {
  1886.     VtUnLock
  1887.     VtClose
  1888.     # return control to the caller
  1889.     eval $cb
  1890. }
  1891. proc UiBuildMenus {form} {
  1892.     global appvals
  1893.     set helpMenuItemList [list \
  1894.         ON_CONTEXT \
  1895.         ON_WINDOW \
  1896.         ON_KEYS \
  1897.         INDEX \
  1898.         ON_HELP]
  1899.     set menuBar [VtMenuBar $form.menuBar \
  1900.             -helpMenuItemList $helpMenuItemList]
  1901.     VxSetVar $form menuBar $menuBar
  1902.     # Main object menu
  1903.     UiBuildObjectMenu $menuBar
  1904.     # Options menu
  1905.     UiBuildOptionsMenu $menuBar
  1906.     return $menuBar
  1907. }
  1908. proc UiBuildObjectMenu {parent} {
  1909.     global appvals
  1910.     set label $appvals(object) 
  1911.     set mnemonic $appvals(objectmn) 
  1912.     set fileMenu [VtPulldown $parent.fileMenu \
  1913.             -label $label \
  1914.             -mnemonic $mnemonic \
  1915.             ]
  1916.     VxSetVar $parent fileMenu $fileMenu
  1917.     set add [VtPushButton $fileMenu.add \
  1918.         -label [IntlMsg ENTRY_MENU_ADD_LBL] \
  1919.         -mnemonic [IntlMsg ENTRY_MENU_ADD_MN]  \
  1920.         -shortHelpCallback SaShortHelpCB \
  1921.         -shortHelpString [IntlMsg ENTRY_MENU_ADD_SH] \
  1922.         -callback UiAddEntryCB  \
  1923.         -autoLock UiAddEntryCB]
  1924.     VxSetVar $parent add $add
  1925.     set delete [VtPushButton $fileMenu.delete \
  1926.         -label [IntlMsg ENTRY_MENU_DELETE_LBL] \
  1927.         -mnemonic [IntlMsg ENTRY_MENU_DELETE_MN]  \
  1928.         -shortHelpCallback SaShortHelpCB \
  1929.         -shortHelpString [IntlMsg ENTRY_MENU_DELETE_SH] \
  1930.         -callback UiDeleteEntryCB  \
  1931.         -autoLock UiDeleteEntryCB]
  1932.     VxSetVar $parent delete $delete
  1933.     set modify [VtPushButton $fileMenu.modify \
  1934.         -label [IntlMsg ENTRY_MENU_MODIFY_LBL] \
  1935.         -mnemonic [IntlMsg ENTRY_MENU_MODIFY_MN]  \
  1936.         -shortHelpCallback SaShortHelpCB \
  1937.         -shortHelpString [IntlMsg ENTRY_MENU_MODIFY_SH] \
  1938.         -callback UiModifyEntryCB  \
  1939.         -autoLock UiModifyEntryCB]
  1940.     VxSetVar $parent modify $modify
  1941.     VtSeparator $fileMenu.s1
  1942.     set moveUp [VtPushButton $fileMenu.moveUp \
  1943.         -label [IntlMsg ENTRY_MENU_UP_LBL] \
  1944.         -mnemonic [IntlMsg ENTRY_MENU_UP_MN]  \
  1945.         -shortHelpCallback SaShortHelpCB \
  1946.         -shortHelpString [IntlMsg ENTRY_MENU_UP_SH] \
  1947.         -callback UiMoveUpEntryCB  \
  1948.         -autoLock UiMoveUpEntryCB]
  1949.     VxSetVar $parent moveUp $moveUp
  1950.     set moveDown [VtPushButton $fileMenu.moveDown \
  1951.         -label [IntlMsg ENTRY_MENU_DOWN_LBL] \
  1952.         -mnemonic [IntlMsg ENTRY_MENU_DOWN_MN]  \
  1953.         -shortHelpCallback SaShortHelpCB \
  1954.         -shortHelpString [IntlMsg ENTRY_MENU_DOWN_SH] \
  1955.         -callback UiMoveDownEntryCB  \
  1956.         -autoLock UiMoveDownEntryCB]
  1957.     VxSetVar $parent moveDown $moveDown
  1958.     VtSeparator $fileMenu.s2
  1959.     set save [VtPushButton $fileMenu.save \
  1960.         -label [IntlMsg ENTRY_MENU_SAVE_LBL] \
  1961.         -mnemonic [IntlMsg ENTRY_MENU_SAVE_MN]  \
  1962.         -shortHelpCallback SaShortHelpCB \
  1963.         -shortHelpString [IntlMsg ENTRY_MENU_SAVE_SH] \
  1964.         -callback UiSaveCB  \
  1965.         -autoLock UiSaveCB]
  1966.     VxSetVar $parent save $save
  1967.     VtSeparator $fileMenu.s3
  1968.     set exitMenu $fileMenu
  1969.     # exit button
  1970.     VtPushButton $exitMenu.exit \
  1971.         -label [IntlMsg ENTRY_MENU_EXIT_LBL] \
  1972.         -mnemonic [IntlMsg ENTRY_MENU_EXIT_MN]  \
  1973.         -shortHelpCallback SaShortHelpCB \
  1974.         -shortHelpString \ [IntlMsg ENTRY_MENU_EXIT_SH \
  1975.                     [list $appvals(title)]] \
  1976.         -callback UiCloseCB  \
  1977.         -autoLock UiCloseCB
  1978. }
  1979. proc UiBuildOptionsMenu {form} {
  1980.     global appvals 
  1981.     # Define the Pulldown itself
  1982.     set optionMenu [VtPulldown $form.optionMenu \
  1983.         -label  [IntlMsg OPTIONS_MENU] \
  1984.         -mnemonic [IntlMsg OPTIONS_MN] \
  1985.         ] 
  1986.     # menu items
  1987.     # short help
  1988.     SaShortHelpLoad $appvals(client)
  1989.     SaShortHelpMenuOptions $optionMenu
  1990.     # toolbar
  1991.     if {$appvals(toolbar) && ![VtInfo -charm]} {
  1992.         UiToolBarBuildMenuOptions $optionMenu
  1993.     }
  1994.     VxSetVar $form optionMenu $optionMenu
  1995.     return $optionMenu
  1996. }
  1997. proc UiToolBarSetVisibilityCB {{cbs {}}} {
  1998.     global appvals
  1999.     set menuBar [VxGetVar $appvals(vtMain) menuBar]
  2000.     set optionMenu [VxGetVar $menuBar optionMenu]
  2001.     set toolBarToggle [VxGetVar $optionMenu toolBarToggle]
  2002.     set visible [VtGetValues $toolBarToggle -value]
  2003.     set toolBar [VxGetVar $appvals(vtMain) toolBar]
  2004.     set toolBarFrame [VxGetVar $appvals(vtMain) toolBarFrame]
  2005.     if {$visible} {
  2006.         # We *must* show the frame first, then the form
  2007.         VtShow $toolBarFrame
  2008.         VtShow $toolBar
  2009.     } else {
  2010.         # We *must* hide the form first, then the frame, in order
  2011.         # to obtain same re-drawing behaviour we get with Sa functions
  2012.         VtHide $toolBar
  2013.         VtHide $toolBarFrame
  2014.     }
  2015.     SaScreenPolicySet $appvals(client) toolbarVisibility $visible
  2016. }
  2017. proc UiToolBarBuildMenuOptions {menu} {
  2018.     global appvals
  2019.     set toolBarToggle [VtToggleButton $menu.toolBarToggle \
  2020.         -label [IntlMsg OPTIONS_TOOLBAR] \
  2021.         -callback UiToolBarSetVisibilityCB \
  2022.         -shortHelpCallback SaShortHelpCB \
  2023.         -shortHelpString [IntlMsg OPTIONS_TOOLBAR_SH] \
  2024.         -value 1]
  2025.     VxSetVar $menu toolBarToggle $toolBarToggle
  2026. }
  2027. proc UiBuildToolBar {form top} {
  2028.     global appvals
  2029.     set toolBarFrame [VtFrame $form.toolBarFrame \
  2030.             -topSide $top \
  2031.             -topOffset 2 \
  2032.             -leftSide FORM \
  2033.             -rightSide FORM \
  2034.             -marginHeight 0 \
  2035.             -marginWidth 0 \
  2036.             -horizontalSpacing 0 \
  2037.             -verticalSpacing 0 \
  2038.             -shadowType IN]
  2039.     set toolBarForm [VtForm $toolBarFrame.toolBarForm \
  2040.             -leftSide FORM \
  2041.             -rightSide FORM \
  2042.             -borderWidth 0 \
  2043.             -marginHeight 0 \
  2044.             -marginWidth 0 \
  2045.             -horizontalSpacing 0 \
  2046.             -verticalSpacing 0]
  2047.     set addTB [VtPushButton $toolBarForm.addTB \
  2048.             -label [IntlMsg TB_ADD] \
  2049.             -topSide FORM \
  2050.             -topOffset 0 \
  2051.             -leftSide FORM \
  2052.             -leftOffset 0 \
  2053.             -rightOffset 0 \
  2054.             -bottomSide FORM \
  2055.             -bottomOffset 0 \
  2056.             -shortHelpCallback SaShortHelpCB \
  2057.             -shortHelpString [IntlMsg ENTRY_MENU_ADD_SH] \
  2058.             -callback UiAddEntryCB \
  2059.             -autoLock UiAddEntryCB]
  2060.     VxSetVar $toolBarForm addTB $addTB
  2061.     set deleteTB [VtPushButton $toolBarForm.deleteTB \
  2062.             -label [IntlMsg TB_DELETE] \
  2063.             -topSide FORM \
  2064.             -leftSide $addTB \
  2065.             -leftOffset 0 \
  2066.             -bottomSide FORM \
  2067.             -bottomOffset 0 \
  2068.             -shortHelpCallback SaShortHelpCB \
  2069.             -shortHelpString [IntlMsg ENTRY_MENU_DELETE_SH] \
  2070.             -callback UiDeleteEntryCB \
  2071.             -autoLock UiDeleteEntryCB]
  2072.     VxSetVar $toolBarForm deleteTB $deleteTB
  2073.     set modifyTB [VtPushButton $toolBarForm.modifyTB \
  2074.             -label [IntlMsg TB_MODIFY] \
  2075.             -topSide FORM \
  2076.             -leftSide $deleteTB \
  2077.             -leftOffset 10 \
  2078.             -bottomSide FORM \
  2079.             -bottomOffset 0 \
  2080.             -shortHelpCallback SaShortHelpCB \
  2081.             -shortHelpString [IntlMsg ENTRY_MENU_MODIFY_SH] \
  2082.             -callback UiModifyEntryCB \
  2083.             -autoLock UiModifyEntryCB]
  2084.     VxSetVar $toolBarForm modifyTB $modifyTB
  2085.     set upTB [VtPushButton $toolBarForm.upTB \
  2086.             -pixmap [IntlMsg BTN_UP_PX] \
  2087.             -topSide FORM \
  2088.             -leftSide $modifyTB \
  2089.             -leftOffset 10 \
  2090.             -bottomSide FORM \
  2091.             -bottomOffset 0 \
  2092.             -shortHelpCallback SaShortHelpCB \
  2093.             -shortHelpString [IntlMsg ENTRY_MENU_UP_SH] \
  2094.             -callback UiMoveUpEntryCB \
  2095.             -autoLock UiMoveUpEntryCB]
  2096.     VxSetVar $toolBarForm upTB $upTB
  2097.     set downTB [VtPushButton $toolBarForm.downTB \
  2098.             -pixmap [IntlMsg BTN_DOWN_PX] \
  2099.             -topSide FORM \
  2100.             -leftSide $upTB \
  2101.             -leftOffset 0 \
  2102.             -rightSide NONE \
  2103.             -bottomSide FORM \
  2104.             -bottomOffset 0 \
  2105.             -shortHelpCallback SaShortHelpCB \
  2106.             -shortHelpString [IntlMsg ENTRY_MENU_DOWN_SH] \
  2107.             -callback UiMoveDownEntryCB \
  2108.             -autoLock UiMoveDownEntryCB]
  2109.     VxSetVar $toolBarForm downTB $downTB
  2110.     VxSetVar $appvals(vtMain) toolBar $toolBarForm
  2111.     VxSetVar $appvals(vtMain) toolBarFrame $toolBarFrame
  2112.     return $toolBarFrame
  2113. }
  2114. proc DomainGetData {} {
  2115.     global appvals
  2116.     set data {}
  2117.     set maxLength 0
  2118.     foreach key [Map:List $appvals(fileid)] {
  2119.         if {[cindex $key 0] == "."} {
  2120.             set partial TRUE
  2121.             set hostName [crange $key 1 len]
  2122.         } else {
  2123.             set partial FALSE
  2124.             set hostName $key
  2125.         }
  2126.         set hostNameLength [clength $hostName]
  2127.         if {$hostNameLength > $maxLength} {
  2128.             set maxLength $hostNameLength
  2129.         }
  2130.         set route [Map:Get $appvals(fileid) $key]
  2131.         set realName [lvarpop route]
  2132.         keylset entry partial $partial
  2133.         keylset entry hostName $hostName
  2134.         keylset entry realName $realName
  2135.         keylset entry route $route
  2136.         lappend data $entry
  2137.     }
  2138.     set mainList [VxGetVar $appvals(vtMain) mainList]
  2139.     if {$maxLength < 30} {
  2140.         set maxLength 30
  2141.     }
  2142.     VxSetVar $mainList maxLength $maxLength
  2143.     return $data
  2144. }
  2145. proc DomainDelete {entries} {
  2146.     global appvals
  2147.     foreach entry $entries {
  2148.         set partial ""
  2149.         set hostName ""
  2150.         keylget entry partial partial
  2151.         keylget entry hostName hostName
  2152.         if {$partial == "TRUE"} {
  2153.             set hostName ".${hostName}"
  2154.         } 
  2155.         Map:Unset $appvals(fileid) $hostName
  2156.     }
  2157. }
  2158. proc DomainAdd {beforeEntry newEntry} {
  2159.     global appvals
  2160.     keylget newEntry partial partial
  2161.     keylget newEntry hostName hostName
  2162.     keylget newEntry realName realName
  2163.     keylget newEntry route route
  2164.     if {$partial == "TRUE"} {
  2165.         set newKey ".$hostName"
  2166.     } else {
  2167.         set newKey $hostName
  2168.     }
  2169.     set newData [concat [string trim $realName] $route]
  2170.     if {$beforeEntry == ""} {
  2171.         # the file was empty !
  2172.         Map:Set $appvals(fileid) $newKey $newData
  2173.     } else {
  2174.         set beforePartial ""
  2175.         set beforeHostName ""
  2176.         keylget beforeEntry partial beforePartial
  2177.         keylget beforeEntry hostName beforeHostName
  2178.         if {$beforePartial == "TRUE"} {
  2179.             set beforeKey ".${beforeHostName}"
  2180.         } else {
  2181.             set beforeKey $beforeHostName
  2182.         }
  2183.         Map:Insert $appvals(fileid) $newKey $newData $beforeKey
  2184.     }
  2185. }
  2186. proc DomainModify {oldEntry newEntry} {
  2187.     global appvals
  2188.     keylget newEntry partial partial
  2189.     keylget newEntry hostName hostName
  2190.     keylget newEntry realName realName
  2191.     keylget newEntry route route
  2192.     if {$partial == "TRUE"} {
  2193.         set newKey ".${hostName}"
  2194.     } else {
  2195.         set newKey $hostName
  2196.     }
  2197.     set newData [concat [string trim $realName] $route]
  2198.     keylget oldEntry partial oldPartial
  2199.     keylget oldEntry hostName oldHostName
  2200.     if {$oldPartial == "TRUE"} {
  2201.         set oldKey ".${oldHostName}"
  2202.     } else {
  2203.         set oldKey $oldHostName
  2204.     }
  2205.     if {[cequal $newKey $oldKey]} {
  2206.         Map:Set $appvals(fileid) $newKey $newData
  2207.     } else {
  2208.         Map:Insert $appvals(fileid) $newKey $newData $oldKey
  2209.         Map:Unset $appvals(fileid) $oldKey
  2210.     }
  2211. }
  2212. proc DomainSwapPosition {entry1 entry2} {
  2213.     global appvals
  2214.     set partial1 ""
  2215.     set hostName1 ""
  2216.     keylget entry1 partial partial1
  2217.     keylget entry1 hostName hostName1
  2218.     if {$partial1 == "TRUE"} {
  2219.         set key1 ".${hostName1}"
  2220.     } else {
  2221.         set key1 $hostName1
  2222.     }
  2223.     set data1 [Map:Get $appvals(fileid) $key1]
  2224.     set partial2 ""
  2225.     set hostName2 ""
  2226.     keylget entry2 partial partial2
  2227.     keylget entry2 hostName hostName2
  2228.     if {$partial2 == "TRUE"} {
  2229.         set key2 ".${hostName2}"
  2230.     } else {
  2231.         set key2 $hostName2
  2232.     }
  2233.     Map:Unset $appvals(fileid) $key1
  2234.     Map:Insert $appvals(fileid) $key1 $data1 $key2
  2235. }
  2236. proc DomainIsModified {} {
  2237.     global appvals
  2238.     if {$appvals(fileid) != -1} {
  2239.         return [Map:Modified $appvals(fileid)]
  2240.     } else {
  2241.         return 0
  2242.     }
  2243. }
  2244. proc DomainEntryExists {hostname} {
  2245.     global appvals
  2246.     set allKeys [string tolower [Map:List $appvals(fileid)]]
  2247.     if {[lsearch -exact $allKeys [string tolower $hostname]] == -1 && \
  2248.         [lsearch -exact $allKeys [string tolower ".${hostname}"]] == -1} {
  2249.         return 0
  2250.     } else {
  2251.         return 1
  2252.     }
  2253. }
  2254. proc DomainSetMainListLabel {maxHostNameLength} {
  2255.     global appvals
  2256.     set mainList [VxGetVar $appvals(vtMain) mainList]
  2257.     if {[VtInfo -charm]} {
  2258.         set labelList [list \
  2259.             [IntlMsg COLUMN_PARTIAL_LBL_CHARM] \
  2260.             [IntlMsg COLUMN_HOST_LBL] \
  2261.             [IntlMsg COLUMN_ROUTE_LBL]]
  2262.     } else {
  2263.         set labelList [list \
  2264.             [IntlMsg COLUMN_PARTIAL_LBL] \
  2265.             [IntlMsg COLUMN_HOST_LBL] \
  2266.             [IntlMsg COLUMN_ROUTE_LBL]]
  2267.     }
  2268.     if {[VtInfo -charm]} {
  2269.         # add 1 for the right margin width
  2270.         set fieldLength [expr $maxHostNameLength + 1]
  2271.         # For charm, we can't really go beyond 60 chars for the
  2272.         # hostname portion of the label
  2273.         if {$fieldLength > 60} {
  2274.             set fieldLength 60
  2275.         }
  2276.         set labelFormat "%-3s%-${fieldLength}s%-20s"
  2277.         set label [format $labelFormat \
  2278.             [lindex $labelList 0] \
  2279.             [lindex $labelList 1] \
  2280.             [lindex $labelList 2]]
  2281.         set header [VxGetVar $appvals(vtMain) header]
  2282.         VtSetValues $header -label $label
  2283.     }
  2284.     # Try to adjust the length to compensate for variable char widths,
  2285.     # and then add 1 for right margin 
  2286.     set fieldLength [expr [AdjustFieldLength $maxHostNameLength] + 1]
  2287.     VtSetValues $mainList -labelFormatList [list \
  2288.         [list STRING 1 14 10] \
  2289.         [list STRING $fieldLength] \
  2290.         [list STRING 20]]
  2291.     VtSetValues $mainList -labelList $labelList
  2292. }
  2293. proc DomainBuildMainList {form top} {
  2294.     global appvals
  2295.     if {[VtInfo -charm]} {
  2296.         set labelList [list \
  2297.             [IntlMsg COLUMN_PARTIAL_LBL_CHARM] \
  2298.             [IntlMsg COLUMN_HOST_LBL] \
  2299.             [IntlMsg COLUMN_ROUTE_LBL]]
  2300.         set labelFormat "%-3s%-20s%-20s"
  2301.         set label [format $labelFormat \
  2302.             [lindex $labelList 0] \
  2303.             [lindex $labelList 1] \
  2304.             [lindex $labelList 2]]
  2305.         set header [VtLabel $form.header \
  2306.                 -labelLeft \
  2307.                 -leftSide FORM \
  2308.                 -leftOffset 3 \
  2309.                 -rightSide FORM \
  2310.                 -topSide $top \
  2311.                 -topOffset 1\
  2312.                 -bottomSide NONE \
  2313.                 -label $label]
  2314.         VxSetVar $form header $header
  2315.         set top $header
  2316.     }
  2317.     set mainList [VtDrawnList $form.mainList \
  2318.             -MOTIF_rows 10 -CHARM_rows 25 \
  2319.             -MOTIF_columns 80 -CHARM_columns 20 \
  2320.             -horizontalScrollBar TRUE \
  2321.             -leftSide FORM \
  2322.             -MOTIF_leftOffset 5 -CHARM_leftOffset 0 \
  2323.             -rightSide FORM \
  2324.             -MOTIF_rightOffset 5 -CHARM_rightOffset 0 \
  2325.             -topSide $top \
  2326.             -MOTIF_topOffset 10 -CHARM_topOffset 0 \
  2327.             -bottomSide NONE \
  2328.             -selection MULTIPLE \
  2329.             -callback DomainMainListCB \
  2330.             -defaultCallback DomainMainListDoubleCB \
  2331.             -autoLock {DomainMainListDoubleCB}]
  2332.     VxSetVar $form mainList $mainList
  2333.     DomainSetMainListLabel 30
  2334.     return $mainList
  2335. }
  2336. proc DomainMainListCB {cbs} {
  2337.     UiMainListCB $cbs
  2338. }
  2339. proc DomainMainListDoubleCB {cbs} {
  2340.     UiMainListDoubleCB $cbs
  2341. }
  2342. proc DomainInit {} {
  2343.     global appvals
  2344.     set appvals(title)     [IntlMsg TITLE $appvals(filename)]
  2345.     set appvals(object)     [IntlMsg OBJECT]    
  2346.     set appvals(objectmn)    [IntlMsg OBJECT_MN]    
  2347.     set appvals(itemname)    [IntlMsg ITEMS]    
  2348. }
  2349. proc DomainWrite {} {
  2350.     global appvals
  2351.     global errorInfo
  2352.     #
  2353.     # commit the changes to file
  2354.     #
  2355.     # force a write since Map:Write will usually only write if
  2356.     # modifcations are made
  2357.     Map:ForceWrites $appvals(fileid)
  2358.     if {[ErrorCatch errStack 0 "Map:Write $appvals(fileid)" result]} {
  2359.         ErrorPush errStack 0 [IntlErrId NONSTDCMD] [list $errorInfo]
  2360.         ErrorPush errStack 1 [IntlErrId WRITE] $appvals(filename)
  2361.     }
  2362.     #
  2363.     # compile the database
  2364.     #
  2365.     set cmd [list exec /etc/mail/makemap hash $appvals(filename) < $appvals(filename) >& /dev/null]
  2366.     if {[ErrorCatch errStack 0 $cmd result]} {
  2367.         ErrorPush errStack 0 [IntlErrId NONSTDCMD] [list $errorInfo]
  2368.         ErrorPush errStack 1 [IntlErrId DATABASE] $appvals(filename).db
  2369.     }
  2370. }
  2371. set appvals(script) [file tail [info script]]    ;# argv[0]: UNIX command name 
  2372. set appvals(client) $appvals(script)        ;# widget strings, preferences
  2373. set appvals(filename) {}            ;# filename of domain table
  2374. set appvals(fileid) -1                ;# backend file id of table
  2375. set appvals(hostname) localhost            ;# name of host being managed
  2376. proc Exit {{code 0}} {
  2377.     # Final exit tasks
  2378.     exit $code
  2379. }
  2380. proc Usage {} {
  2381.     global appvals
  2382.     set usage [IntlErr USAGE $appvals(script)]
  2383.     puts stderr $usage
  2384. }
  2385. proc ParseCommandLine {} {
  2386.     global argv argc optarg opterr optind appvals
  2387.     # scan for commandline flags
  2388.     set optString    "f:h:"
  2389.     set argc [llength $argv]
  2390.     if {$argc == 0} {
  2391.         Usage; Exit 1
  2392.     }
  2393.     set opterr 0
  2394.     while {[set opt [getopt $argc $argv $optString]] != -1} {
  2395.         switch $opt {
  2396.             {f} {
  2397.                 set appvals(filename) $optarg
  2398.             }
  2399.             {h} {
  2400.                 set appvals(hostname) $optarg
  2401.             }
  2402.             {?} {
  2403.                 Usage; Exit 1
  2404.             }
  2405.         }
  2406.     }
  2407.     # process commandline arguments
  2408.     set optCount [expr "$argc - $optind"]
  2409.     if {$optCount > 0} {
  2410.         Usage; Exit 1
  2411.     }
  2412.     if {"$appvals(filename)" == ""} {
  2413.         Usage; Exit 1
  2414.     }
  2415. }
  2416. proc Main {} {
  2417.     global appvals errorInfo
  2418.     # Collect command line options
  2419.     ParseCommandLine
  2420.     # Initialize UI, build main form, present initial view
  2421.     # Init a few globals first
  2422.     DomainInit
  2423.     UiStart
  2424.     # Main UI is now presented and Locked
  2425.     # Time-consuming startup operations can now take place with
  2426.     # optional status messages 
  2427.     #
  2428.     # + collect data to populate main form widgets
  2429.     # + populate main form widgets with live data
  2430.     SaStatusBarSet \
  2431.         [VxGetVar $appvals(vtMain) statusBar] [IntlMsg INIT] 
  2432.     # Show/hide the toolbar, depending on screen policy
  2433.     if {! [VtInfo -charm]} {
  2434.         set cmd "set visibility \[SaScreenPolicyGet $appvals(client) toolbarVisibility\]"
  2435.         if {[ErrorCatch errStack 0 $cmd errMsg] != 0} {
  2436.             set visibility 1
  2437.         }
  2438.         set menuBar [VxGetVar $appvals(vtMain) menuBar]
  2439.         set optionMenu [VxGetVar $menuBar optionMenu]
  2440.         set toolBarToggle [VxGetVar $optionMenu toolBarToggle]
  2441.         set toolBar [VxGetVar $appvals(vtMain) toolBar]
  2442.         set toolBarFrame [VxGetVar $appvals(vtMain) toolBarFrame]
  2443.         VtSetValues $toolBarToggle -value $visibility
  2444.         UiToolBarSetVisibilityCB
  2445.         }
  2446.     # if file does not exist, let the user know
  2447.     if {![file exists $appvals(filename)]} {
  2448.         set main $appvals(vtMain)
  2449.         set dialog [VtInformationDialog $main.exist \
  2450.                 -message [IntlMsg FILE_DOESNT_EXIST] \
  2451.                 -ok]
  2452.         VtShow $dialog
  2453.     }
  2454.     # if file is a directory, show error and exit
  2455.     if {[file isdirectory $appvals(filename)]} {
  2456.         set main $appvals(vtMain)
  2457.         set dialog [VtErrorDialog $main.error \
  2458.             -message [IntlErr DIRECTORY $appvals(filename)] \
  2459.             -ok -okCallback UiCloseCB -wmCloseCallback UiCloseCB]
  2460.         VtShow $dialog
  2461.         VtUnLock
  2462.         VtMainLoop
  2463.         return
  2464.     }
  2465.     # Open the file and read in the data to back end structures
  2466.     if {[ErrorCatch errStack 0 "Map:Open $appvals(filename)" result]} {
  2467.         ErrorPush errStack 0 [IntlErrId NONSTDCMD] [list $errorInfo]
  2468.         ErrorPush errStack 0 [IntlErrId LOAD] $appvals(filename)
  2469.         VtUnLock
  2470.         UiDisplayErrorStacks Main $errStack UiCloseCB
  2471.     } else {
  2472.         set appvals(fileid) $result
  2473.     }
  2474.     # Refresh main form data
  2475.     UiRefreshCB
  2476.     # Select first item, if exists
  2477.     set mainList [VxGetVar $appvals(vtMain) mainList]
  2478.     if {![lempty [VtDrawnListGetItem $mainList -all]]} {
  2479.         VtDrawnListSelectItem $mainList -position 1
  2480.     }
  2481.     # update the count label
  2482.     UiUpdateCountLabel
  2483.     # Set initial focus (list or menu bar)
  2484.     UiSetAppFocus
  2485.     # Set sensitivity of all main screen ui selection devices
  2486.     UiSensitizeMainFunctions
  2487.     # Setup complete
  2488.     # Wait for user events
  2489.     SaStatusBarClear [VxGetVar $appvals(vtMain) statusBar]
  2490.     VtUnLock
  2491.     VtMainLoop
  2492. }
  2493. proc CloseWithUi {} {
  2494.     set saveConfirmDlg [UiBuildSaveConfirmDialog]
  2495.     VtShow $saveConfirmDlg
  2496. }
  2497. proc CloseAfterUi {} {
  2498.     Exit
  2499. }
  2500. proc Refresh {} {
  2501.     global appvals
  2502.     # Populate main form data here
  2503.     set data {}
  2504.     # TODO
  2505.     # Setup simple example using the "who" module
  2506.     # Except for the following line, Refresh should be generic
  2507.     # and usable as is.
  2508.     # load Ui
  2509.     set data [DomainGetData]
  2510.     UiMainListSetItems $data
  2511. }
  2512. ErrorTopLevelCatch {Main} $appvals(script)
  2513.