home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1998 March / Macworld (1998-03) (Disk 1).dmg / Shareware World / Utilities / Text Processing / Alpha / Tcl / SystemCode / appPaths.tcl < prev    next >
Encoding:
Text File  |  1997-12-10  |  9.3 KB  |  371 lines  |  [TEXT/ALFA]

  1.  
  2. namespace eval app {}
  3. namespace eval file {}
  4. namespace eval dialog {}
  5.  
  6. proc app::ensureRunning {sig {in_front 0}} {
  7.     # See if a process w/ any of the acceptable 
  8.     # sigs already running.
  9.     if [app::isRunning $sig name] {
  10.         if {$in_front} {switchTo '$sig'}
  11.         return $name
  12.     }
  13.     if {[catch {nameFromAppl $sig} name]} {
  14.         alertnote "Can't find app w/ sig '$sig'.\
  15.           Try rebuilding your desktop or changing your helper apps."
  16.         error ""
  17.     }
  18.     if {![file exists $name]} {
  19.         alertnote "Sig '$sig' is mapped to '$name', which doesn't\
  20.           exist. Try changing your helper apps."
  21.         error ""
  22.     }
  23.     # Launch the app
  24.     if {$in_front} {
  25.         launch -f $name
  26.     } else {
  27.         launch $name
  28.     }
  29.     hook::callAll launch $sig
  30.     return $name
  31. }
  32.  
  33. # Switch to 'sig', launching if necesary
  34. proc app::launchFore {sig} {
  35.     app::ensureRunning $sig 1
  36. }
  37.  
  38. # Ensure that the app is at least running in the background.
  39. proc app::launchBack {sig} {
  40.     app::ensureRunning $sig 0
  41. }
  42.  
  43. proc app::launchAnyOfThese {sigs sig {prompt "Please locate the application:"}} {
  44.     app::launchBackSigs $sigs $sig $prompt 0
  45. }
  46. proc app::launchElseTryThese {sigs sig {prompt "Please locate the application:"}} {
  47.     app::launchBackSigs $sigs $sig $prompt 1
  48. }
  49.  
  50. # Check to see if any of the 'sigs' is running. If so, return its name.
  51. # Otherwise, attempt to launch the file named by 'sig'.
  52. proc app::launchBackSigs {sigs sig {prompt "Please locate the application:"} {running_first 1} } {
  53.     global $sig
  54.     if {$running_first || ![info exists $sig] || [catch {nameFromAppl [set $sig]}]} {        
  55.         app::setRunningSig $sigs $sig
  56.         app::getSig $prompt $sig
  57.     }
  58.     return [app::launchBack [set $sig]]
  59. }
  60.  
  61. proc app::getSig {prompt sig} {
  62.     global $sig modifiedVars
  63.     if {[catch {nameFromAppl [set $sig]}]} {
  64.         set $sig [getFileSig [getfile $prompt]]
  65.         lappend modifiedVars $sig
  66.     }
  67. }
  68.  
  69.  
  70. proc app::setRunningSig {sigs sig} {
  71.     global $sig    modifiedVars
  72.     if [app::isRunning $sigs name s] {
  73.         if {![info exists $sig] || ($s != [set $sig])} {
  74.             set    $sig $s
  75.             lappend    modifiedVars $sig
  76.         }
  77.         return 1
  78.     }
  79.     return 0
  80. }
  81.  
  82. ## 
  83.  # -------------------------------------------------------------------------
  84.  # 
  85.  # "app::isRunning" --
  86.  # 
  87.  #  Is an app with one of the given sigs running.  Set the global $sig
  88.  #  to the name of that thing if it is
  89.  #  
  90.  #  {"Finder" "MACS" 978944 182209 }
  91.  #  
  92.  #  Much improved by Vince to avoid scanning the processes list one at a
  93.  #  time.
  94.  #  
  95.  #  We have to workaround a bug in tcl 7.4-7.5
  96.  # -------------------------------------------------------------------------
  97.  ##
  98. if {[info tclversion] < 8.0} {
  99. proc app::isRunning {sigs {n ""} {s ""}} {
  100.     if {$n != ""} {upvar $n name}
  101.     if {$s != ""} {upvar $s sig}
  102.     return [regexp "\"(\[^\"\]+)\" \"([join [quote::Regfind [quote::Regfind $sigs]] |])\" " [processes] "" name sig]
  103. }
  104. } else {
  105. proc app::isRunning {sigs {n ""} {s ""}} {
  106.     if {$n != ""} {upvar $n name}
  107.     if {$s != ""} {upvar $s sig}
  108.     return [regexp "\"(\[^\"\]+)\" \"([join [quote::Regfind $sigs] |])\" " [processes] "" name sig]
  109. }
  110. }
  111.  
  112.  
  113. proc printLeftHeader {pg} {
  114.     global printHeader printHeaderTime printHeaderFullPath
  115.     
  116.     if {!$printHeader} return ""
  117.     
  118.     if {$printHeaderFullPath} {
  119.         set text [win::Current]
  120.     } else {
  121.         set text [win::CurrentTail]
  122.     }
  123.     
  124.     if {$printHeaderTime} {
  125.         append text "      [join [mtime [now] short]]"
  126.     }
  127. }
  128.  
  129. proc printRightHeader {pg} {
  130.     return "Page $pg"
  131. }
  132.  
  133. proc revertToBackup {} {
  134.     global backup backupExtension backupFolder win::Modes 
  135.  
  136.     set fname [win::Current]
  137.     set dir $backupFolder
  138.     set bname "$dir:[file tail $fname]$backupExtension"
  139.     if {![file exists $bname]} {
  140.         message "Backup file '$bname' does not exist"
  141.         return
  142.     }
  143.     
  144.     if [dialog::yesno "Revert to backup dated '[join [mtime [file mtime $bname]]]'?"] {
  145.         killWindow
  146.         
  147.         edit $bname
  148.         saveAs -f $fname
  149.     }
  150. }
  151.  
  152.  
  153. ## 
  154.  # -------------------------------------------------------------------------
  155.  # 
  156.  # "app::registerMultiple" --
  157.  # 
  158.  #  Does the dirty work so a mode can use different icons for its menu
  159.  #  according to which application a particular user has selected for
  160.  #  that mode.  The arguments are as follows:
  161.  #  
  162.  #  type - a prefix such as 'java' which is used to create variables
  163.  #         such as 'javaSig' 'javaMenu'
  164.  #  creators - the list of recognised creators (1st is default)
  165.  #  icons - the list of icon resources
  166.  #  menurebuild - the procedure which is used to rebuild the mode menu
  167.  #  
  168.  #  here's an example:
  169.  #  
  170.  #    app::registerMultiple java [list Javc WARZ] \
  171.  #      [list •140 •285] rebuildJavaMenu
  172.  #      
  173.  #  of course the rebuild procedure must use the correct icon like this:
  174.  #  
  175.  #    proc rebuildJavaMenu {} {
  176.  #        global javaMenu
  177.  #        menu -n $javaMenu -p javaMenuProc {
  178.  #        }
  179.  #      }
  180.  #    
  181.  #    Note: this procedure ensures the menu is created the first time it
  182.  #    is called.
  183.  # --Version--Author------------------Changes-------------------------------
  184.  #    1.0     <darley@fas.harvard.edu> original
  185.  # -------------------------------------------------------------------------
  186.  ##
  187. proc app::registerMultiple {type creators icons menurebuild} {
  188.     global ${type}Sig multiApp
  189.     if ![info exists ${type}Sig] {
  190.         set ${type}Sig [lindex $creators 0]
  191.     }
  192.     set multiApp($type) [list $creators $icons $menurebuild]
  193.     app::multiChanged ${type}Sig
  194.     trace variable ${type}Sig w app::multiChanged
  195. }
  196.  
  197. ## 
  198.  # -------------------------------------------------------------------------
  199.  # 
  200.  # "app::multiChanged" --
  201.  # 
  202.  #  Utility procedure used by the above.  No need to call it manually.
  203.  # -------------------------------------------------------------------------
  204.  ##
  205. proc app::multiChanged {type args} {
  206.     set type [string range $type 0 [expr [string last "Sig" $type] -1]]
  207.     global ${type}Menu ${type}Sig multiApp
  208.     # remove old menu
  209.     catch {removeMenu [set ${type}Menu]}
  210.     # update the icon according to signature
  211.     set info $multiApp($type)
  212.     if {[set i [lsearch -exact [lindex $info 0] [set ${type}Sig]]] == -1} {
  213.         set i 0
  214.     }
  215.     set ${type}Menu [lindex [lindex $info 1] $i]
  216.     # rebuild the menu
  217.     eval [lindex $multiApp($type) 2]
  218.     # insert the new menu
  219.     insertMenu [set ${type}Menu]
  220. }
  221.  
  222. proc file::ensureDirExists {dir} {
  223.     if ![file exists $dir] {
  224.         file::ensureDirExists [file dirname $dir]
  225.         mkdir $dir
  226.         return 1
  227.     }
  228.     return 0
  229. }
  230.  
  231.  
  232. proc file::openAny {file} {
  233.     getFileInfo $file a
  234.     if {$a(type) == "TEXT"} {
  235.         edit $file
  236.         return
  237.     } else {
  238.         sendOpenEvent -noreply Finder "${file}"
  239.     }
  240. }
  241.  
  242. proc file::renameTo {} {
  243.     set c [win::Current]
  244.     if {![file exists $c]} { alertnote "Not a file window!" ; return }
  245.     set new [prompt "New name for file:" [file tail $c]]
  246.     if [file exists [set to [file dirname $c]:$new]] {
  247.         alertnote "Already exists!"
  248.         return
  249.     }
  250.     killWindow
  251.     moveFile $c $to
  252.     edit $to
  253. }
  254.  
  255. proc helperApps {} {
  256.     set sigs [info globals *Sig]
  257.     regsub -all {Sig} $sigs {} sigs
  258.     set sig [listpick -p "Change/inspect which helper?" [lsort $sigs]]
  259.     set sig ${sig}Sig
  260.     global $sig
  261.     if ![info exists $sig] { set $sig "" }
  262.     set nsig [dialog::askFindApp $sig [set $sig]]
  263.     if {$nsig != "" && [set $sig] != $nsig} {
  264.         set $sig $nsig
  265.         global modifiedVars
  266.         lappend modifiedVars $sig
  267.     }
  268. }
  269.  
  270. proc dialog::askFindApp {var sig} {
  271.     if {$sig == ""} {
  272.         set text "Currently unassigned.   Set?"
  273.     } elseif {[catch {nameFromAppl '$sig'} name]} {
  274.         set text "App w/ sig '$sig' doesn't seem to exist.   Change?"
  275.     } else {
  276.         set text "Current value is '$name'.   Change?"
  277.     }
  278.     if [dialog::yesno $text] {
  279.         set nsig [dialog::findApp $var $sig]
  280.         set app [nameFromAppl $nsig]
  281.         if [dialog::yesno "Are you sure you want to set $var to '$nsig' (mapped to '$app')?"] {
  282.             return $nsig
  283.         }
  284.     }
  285.     return ""
  286. }
  287.  
  288. proc dialog::findApp {var sig} {
  289.     global ${var}s modifiedVars
  290.     if [info exists ${var}s] {
  291.         # have a list of items
  292.         set sigs [set ${var}s]
  293.         
  294.         set s 0
  295.         foreach f $sigs {
  296.             if ![catch {nameFromAppl $f} path] {
  297.                 lappend items [file tail $path]
  298.                 lappend itemsigs $f
  299.                 incr s
  300.             }
  301.         }
  302.         if $s {
  303.             lappend items "-" "Locate manually…"
  304.             if [catch {dialog::optionMenu "Select a new helper for '$var':" \
  305.               $items "" 1} p] {
  306.                 return ""
  307.             }
  308.             # we removed a bunch of items above, so have to look here
  309.             if {$p < $s} {
  310.                 return [lindex $itemsigs $p]
  311.             }
  312.         }
  313.         if {!$s || $p >= $s} {
  314.             set nsig [dialog::_findApp $var $sig]
  315.             if {$nsig != ""} {
  316.                 if {[lsearch $sigs $nsig] == -1} {
  317.                     lappend ${var}s $nsig
  318.                     lappend modifiedVars ${var}s
  319.                 }
  320.             }
  321.         } else {
  322.             set nsig [lindex $sigs $p]
  323.         }
  324.         return $nsig
  325.     } else {
  326.         return [dialog::_findApp $var $sig]
  327.     }
  328. }
  329.  
  330. proc dialog::_findApp {var sig} {
  331.     if [catch {getfile "Locate new helper for '$var':"} path] { return "" }
  332.     set nsig [getFileSig $path]
  333.     set app [nameFromAppl $nsig]
  334.     if {$app != $path} {
  335.         alertnote "Appl sig '$nsig' is mapped to '$app', not '$path'. Remove the former, or rebuild your desktop."
  336.         return ""
  337.     }
  338.     return $nsig
  339. }
  340.  
  341. #================================================================================
  342. # Excalibur is the only Mac spell-checker that I know of which will handle 
  343. # LaTeX as well as ordinary text.
  344.  
  345.  
  346. proc spellcheckWindow {} {
  347.     global resumeRevert
  348.  
  349.     set name [app::launchFore XCLB]
  350.  
  351.     if {[winDirty]} {
  352.         if {[dialog::yesno "Save '[win::CurrentTail]'?"]} {
  353.             save
  354.         }
  355.     }
  356.     sendOpenEvent noReply [file tail $name] [win::Current]
  357.     set resumeRevert 1
  358. }
  359.  
  360. proc spellcheckSelection {} {
  361.     if {[getPos] == [selEnd]} {
  362.         beep
  363.         message "No selection"
  364.         return;
  365.     }
  366.     set name [app::launchBack XCLB]
  367.     copy
  368.     switchTo $name
  369. }
  370.  
  371.