1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
|
#! /bin/sh
# restart with wish: \
exec wish "$0"
#
# Name : dfm-execute.tcl
# Zweck: Eingabedialog fr Programmstarts.
# Autor: Christian V. J. Brssow <cvjb@bigfoot.de>
# Stand: Mit 03 Feb 1999 19:05:05 MET
# Notiz: BETA; en_GB (Skript wurde mit TAB=3 geschrieben; VIM)
# BESCHREIBUNG
#
# Durch Drcken der Escape-Taste wird das Programm abgebrochen.
#
# Durch Drcken der F1-Taste erhlt der Anwender eine kurze Angabe der
# Tastenbelegung.
# VORGABEN
# Eingabefeld ist beim Start leer.
set cmd ""
# PROZEDUREN
# Ersatz fr tk_dialog.
# Setzt im Gegensatz zu tk_dialog die Schrift fr die Meldung
# nicht explizit.
# Steht hier, damit dieses Skript portabel bleibt. Bei dem Autor selbst
# wird diese Funktion durch sog. Autoloading aus einer Library geladen.
proc new_tk_dialog {w title text bitmap default args} {
global tk_priv
# Toplevelfenster erstellen.
catch {destroy $w}
toplevel $w -class Dialog
wm title $w $title
wm iconname $w Dialog
# Fenster in zwei Hauptframes vertikal unterteilen.
# Oberer Hauptframe.
frame $w.top -relief raised -borderwidth 1
pack $w.top -side top -fill both
# Im oberen Frame wird die gewnschte Nachricht angezeigt.
message $w.top.msg -aspect 320 -text $text
pack $w.top.msg -side right -expand 1 -fill both -padx 5m -pady 5m
# Ebenso wird optional, links neben der Nachricht eine Bitmap
# ausgegebe.
if {$bitmap != ""} {
label $w.top.bitmap -bitmap $bitmap
pack $w.top.bitmap -side left -padx 5m -pady 5m
}
# Unterer Hauptframe.
frame $w.bot -relief raised -borderwidth 1
pack $w.bot -side bottom -fill both
# Im unteren Frame werden die angegebene Schalter positioniert.
# Falls angegeben, wird der Vorgabeschalter gesondert hervorgehoben.
set i 0
foreach but $args {
button $w.button$i -text $but -command "set tk_priv(button) $i"
if {$i == $default} {
# Vorgabeschalter.
frame $w.bot.default -relief sunken -borderwidth 1
raise $w.button$i $w.bot.default
pack $w.bot.default -side left -expand 1 -padx 2m -pady 1m
pack $w.button$i -in $w.bot.default -padx 1m -pady 1m -ipadx 0m -ipady 0m
bind $w <Return> "$w.button$i flash ; set tk_priv(button) $i"
} else {
# Normaler Schalter.
pack $w.button$i -in $w.bot -side left -expand 1 -padx 2m -pady 2m\
-ipadx 0m -ipady 0m
}
incr i
}
# Das Fenster komplett vom Schirm entfernen, sein Layout aktualisieren.
# Dann in der Mitte des Bildschirms positionieren; Angaben hierzu werden
# aus seiner aktuellen Gre berechnet. Wenn alles klar ist, dann das
# Fenster wieder auf dem Schirm darstellen.
wm withdraw $w
update idletasks
set x [expr [winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
- [winfo vrootx [winfo parent $w]]]
set y [expr [winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
- [winfo vrooty [winfo parent $w]]]
wm geometry $w +$x+$y
wm deiconify $w
# Das Fenster erhlt den Focus und den Grab; Vorgngerfocus wird
# aber gesichert.
set old_focus [focus]
grab $w
focus $w
# Jetzt solange warten, bis der Benutzer einen Knopf bettigt.
# Dann das Fenster lschen und den alten Focus wieder herstellen.
# Zuletzt wird die Kennung des gedrckten Knopfs als Funktionswert
# zurckgeliefert.
tkwait variable tk_priv(button)
destroy $w
focus $old_focus
return $tk_priv(button)
}
# In der Umgebungsvariablen PATH nach der Datei $dat* suchen.
# Wird $dat* gefunden, dann wird der gefundene Pfad, mit $dat (expandiert)
# am Ende, als Ergebnis geliefert, sonst 1; vgl. tcl-Kommando catch.
proc full_path dat {
# Es wird eine Umgebungsvariable abgefragt.
global env
# Sicher ist sicher: berflssige Leerstellen vom Suchbegriff entfernen.
set prg [string trim $dat]
# Suche beginnen. Es werden die Verzeichnisse in PATH durchsucht.
foreach dir [split $env(PATH) ":"] {
# Gesucht wird unter Anwendung von Dateinamen-Globbing.
# Das Ergebnis steht in path.
if ![catch {glob $dir/$dat*} path] {
# Die erste gefundene Stelle wird ausgegeben und die Prozedur
# wird verlassen.
return [lindex $path 0]
}
}
# Hier landet man nur, wenn nichts gefunden wurde: es wird 1 zurckgeliefert.
return 1
}
# Datei $dat in der Umgebungsvariablen PATH suchen.
# Mgliche Ergebinsse:
# - gefunden => vollstndigen Pfad von $dat (evtl. expandiert: globbing)
# - nicht gefunden => $dat unverndert zurckliefern
proc search_path dat {
set path [full_path $dat]
if {$path == 1} {
return $dat
} else {
return $path
}
}
# Programm starten.
proc start cmd {
# Annahme: alles vom Zeilenanfang bis zum ersten Leerzeichen ist der
# Befehlsname/pfad; der Rest sind die Argumente.
regexp {^([-A-Za-z0-9./]+)[ ]*(.*)$} $cmd cmd prg args
if ![catch { eval exec $prg $args & } errorCode] {
exit
} else {
new_tk_dialog .err_d {Error} \
"Execution failed:\n$errorCode" \
error 0 { Ok }
}
}
# Kurze Hilfe ausgeben.
proc help {} {
new_tk_dialog .help_d {Help} {Keys:
Enter : execute given program
Esc : cancel execution
Tab : search for given name in PATH
and try to complete the name
F1 : show this short help
} question 0 { OK }
}
# WIDGETS DEFINIEREN
frame .plane -relief raised -borderwidth 1
# Bezeichner fr die erwartete Eingabe.
label .plane.label -text "EXEC:"
# Eingabezeile.
entry .plane.entry -textvariable cmd -width 36 -relief sunken -borderwidth 1
# EVENTS
# Globale Events
# Return-Taste => Eingabe bernehmen und damit den Programm starten.
# ESC-Taste => Eingabe verwerfen und Programm abbrechen.
bind all <Return> {start $cmd}
bind all <Escape> {exit}
bind all <F1> {help}
# Dieses Binding lscht die Auswahl, die durch das lokale Binding
# unter .plane.entry automatisch aktiviert wird, wieder.
bind all <Tab> {.plane.entry selection clear}
# Lokale Events
# Tab-Taste => $cmd durch Globbing in $env(PATH) suchen.
bind .plane.entry <Tab> {set cmd [search_path $cmd] ; .plane.entry icursor end}
# FOCUS
# Den Focus bekommt die Eingabezeile.
focus .plane.entry
# SELEKTION
# Es gibt keine Vorgabe in der Eingabezeile.
# Sicher ist sicher: Auswahl explizit lschen.
.plane.entry selection clear
# WIDGETS DARSTELLEN
# Zuerst die Unterwidgets.
pack .plane.label -side left -fill x
pack .plane.entry -side left -fill x -expand 1
# Zuletzt das Hauptwidget, dadurch erscheinen das Widgetensemble
# quasi auf einen Schlag.
pack .plane -fill x
# APPLIKATIONSFENSTER
# Das Fenster ist ein sog; transientes Fenster.
# Diese Fenster ist sein eigener Master! Dies ist ein etwas
# unsauberer Trick, um ein transientes Fenster ohne "wirkliches"
# Masterfenster zu erzeugen.
wm transient . .
# Fenster- und Icontitel.
wm title . "Execute"
wm iconname . "exec"
# Fixe Fenstergre.
wm geometry . {}
wm resizable . 0 0
# Fenster in der Bildschirmmitte positionieren.
# Zuerst mu die Fenstermitte bestimmt werden.
wm withdraw .
set x [expr [winfo screenwidth .]/2 - [winfo reqwidth .]/2 \
- [winfo vrootx .]]
set y [expr [winfo screenheight .]/2 - [winfo reqheight .]/2 \
- [winfo vrooty .]]
wm geometry . +$x+$y
wm deiconify .
# Explizit alles neu darstellen.
update idletasks
# vim: set tw=128 sw=3 ts=3 nocindent:
|