File: dfm-execute.tcl

package info (click to toggle)
dfm 0.99.7-7
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 2,440 kB
  • ctags: 903
  • sloc: ansic: 13,315; makefile: 357; tcl: 289; sh: 283; sed: 93
file content (261 lines) | stat: -rw-r--r-- 7,120 bytes parent folder | download | duplicates (4)
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: