File: fileio.tcl

package info (click to toggle)
ucbmpeg 1r2-6
  • links: PTS
  • area: non-free
  • in suites: hamm, potato, slink
  • size: 9,504 kB
  • ctags: 7,643
  • sloc: ansic: 79,920; tcl: 2,985; perl: 313; asm: 284; makefile: 269; csh: 13
file content (416 lines) | stat: -rw-r--r-- 12,901 bytes parent folder | download
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
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
#
# fileio.tcl - a simple file save/load utility.
#
# Routines:
#	FileDialog
#	

set file(retry) 0

#--------------------------------------------------------------------
# SaveDialog --
#
#	Create a Save dialog box, which consists of a file/directory
#	chooser and a panel to specify the file creation permissions.
#	This procedure is invoked to save the internal database.
#
# dialogTitle	The title for the dialog.
# saveCmd       Command to execute to save.
#--------------------------------------------------------------------
proc SaveDialog {{dialogTitle "Save Dialog"} \
                 {saveCmd "puts -nonewline stderr {Save in: }; puts stderr"}} {
  global file 

  set name $file(name)
  set w .save
  IOBox $w $dialogTitle Save $saveCmd $name
  
  label $w.p.right.per -text " Permissions"
  set q $w.p.right.1
  frame $q -relief sunken -bd 1
  frame $q.per -relief sunken
  label $q.per.empty -text "" -padx 0 -pady 0
  label $q.per.read -text Read -padx 0 -pady 0
  label $q.per.write -text Write -padx 0 -pady 0
  pack $q.per.empty $q.per.read $q.per.write -side top -expand yes
  frame $q.group
  label $q.group.label -text Group -padx 0
  checkbutton $q.group.read -var file(gr) -com {SetMask $file(gr) 040} \
  	-text "" -padx 0 -pady 0 -relief flat -anchor center
  checkbutton $q.group.write -var file(gw) -com {SetMask $file(gw) 020} \
  	-text "" -padx 0 -pady 0 -relief flat -anchor center
  pack $q.group.label -side top -anchor w
  pack $q.group.read $q.group.write -side top 
  frame $q.world
  label $q.world.label -text World -padx 0
  checkbutton $q.world.read -var file(wr) -com {SetMask $file(wr) 004} \
  	-text "" -padx 0 -pady 0 -relief flat -anchor center
  checkbutton $q.world.write -var file(ww) -com {SetMask $file(ww) 002} \
  	-text "" -padx 0 -pady 0 -relief flat -anchor center
  pack $q.world.label $q.world.read $q.world.write -side top
  pack $q.per $q.group $q.world -side left

  pack $w.p.right.1 -side bottom
  pack $w.p.right.per -side bottom -anchor w

  if $file(mask)&040 {$q.group.read select}
  if $file(mask)&020 {$q.group.write select}
  if $file(mask)&004 {$q.world.read select}
  if $file(mask)&002 {$q.world.write select}

  tkwait window $w
}

#--------------------------------------------------------------------
# LoadDialog --
#
# 	Create a Load dialog box, which consists of a file/directory
#	chooser.  Uses the global variable $file to identify default file
#   and permissions.
#
# dialogTitle   The title for the dialog.
# LoadCmd       Command to execute to load.
#--------------------------------------------------------------------
proc LoadDialog {{dialogTitle "Load Dialog"} \
		{loadCmd "puts -nonewline stderr {Load from: }; puts stderr"}} {
  global file

  set w .load
  IOBox $w $dialogTitle Open $loadCmd $file(name)

}

#--------------------------------------------------------------------
# SetMask --
#
#	A utility procedure used by SaveBox to set or clear various
#	bits in the file creation permission mask.
#
# add 	0 means remove permission, 1 means add permission.
# prec 	The bits of permission to add or remove.
#--------------------------------------------------------------------
proc SetMask {add prec} {
  global file
  if $add {
    set file(mask) [expr $file(mask)|$prec]
  } else {
    set file(mask) [expr $file(mask)&~$prec]
  }
}

#--------------------------------------------------------------------
# IOBox --
#
#	Create an iobox, which consists of a title, entry, scrollbox,
#	and two buttons.  The iobox allows the user to select a
#	directory of filename by typing in the entry widget and
#	pressing return, or by double clicking in the listbox.  When
#	a directory is selected, the listbox changes to display that
#	directory.  When a file is selected, the command passed in
#	by the user is called with the name of the file as an
#	argument.  
#
# 	If the user specified command returns an error, then the
#	window remains posted.  Otherwise, when the user specified
#	command sucessfully finishes, this window goes away.
#
# w 	  Name for the iobox.
# title   Title for the iobox.
# button  String that goes in the first button.
# cmd 	  The user specified command to execute when a file is selected.
# name 	  The initial string that goes in the entry in the filebox.
#--------------------------------------------------------------------
proc IOBox {w title button cmd name} {
  global file
  
  Dialog $w 1 $title
  frame $w.p -bd 1 -relief raised 
  label $w.p.cwd -anchor w

  set file(working) $name
  set file(cancel) 0
  frame $w.p.left
  label $w.p.left.label -text Filename
  entry $w.p.left.entry -relief sunken
  ScrollBox $w.p.left.list 20x15
  pack $w.p.left.label -side top -anchor w
  pack $w.p.left.entry -side top -expand yes -fill x -padx 3
  pack $w.p.left.list -side top -fill x -pady 7

  set cmd "IOFinished {$cmd} $w"
  set list $w.p.left.list.list
  bind $list <Any-Double-Button> \
    "FilePress $w \"\[%W get \[%W nearest %y]]\" {$cmd}"
  bind $list <Any-ButtonRelease> \
    "if %x>0&&%x<\[winfo width $list] {Editname $w}"
  Editname $w
  $w.p.left.entry select from 0
  $w.p.left.entry select to end
  Browse $w
  Focus $w.p.left.entry  

  frame $w.p.right 
  set b [DefaultButton $w.p.right.def -text $button -padx 0 \
  	-com "FileReturn $w {$cmd}"]
  button $w.p.right.can -text Cancel -pady 5 -padx 0 -wid 7 \
  	-com "destroy $w; set file(cancel) 1 "

  pack $w.p.right.def -side top -pady 5 -padx 40
  pack $w.p.right.can -side top -pady 5
  
  pack $w.p.cwd -side bottom -fill x
  pack $w.p.left -side left -padx 4
  pack $w.p.right -side right -fill y -pady 8
  pack $w.p -side top -expand yes -fill both

  bind $w.p.left.entry <Any-Return> "$b flash; $b invoke"
}

#--------------------------------------------------------------------
# IOFinished --
#
# 	A utility procedure used by IOBox.  If the user command
#	succeeds, then destroy the window, else continue.
#
# cmd 	The command to execute.
# w 	The window to destroy.
# file 	The file to run the command on.
#--------------------------------------------------------------------
proc IOFinished {cmd w name} {
  global file
  
  if [catch {eval $cmd $name} msg] {
    error $msg "" WARN
  }
  if $file(retry)==0 {
    destroy $w
  }
  set file(retry) 0
}

#--------------------------------------------------------------------
# FileReturn --
#
# 	Utility procedure invoked when the Return key is pressed or
#	the default button is invoked.
#
#	  If the entry widget contains the name of a directory, open
#	that directory.
#	  Otherwise, if the listbox contains a selected element, open
#	the file or directory named by that element.
#	  Otherwise, open the file name in the entry widget.
#
# w	The iobox
# cmd	The command to execute when a file is selected.
#--------------------------------------------------------------------
proc FileReturn {w cmd} {
  global file

  set goto [$w.p.left.entry get]
  if {$goto == "" || [file isdirectory [FilePath $goto]] == 0} {
    set sel [$w.p.left.list.list cursel]
    if {$sel != ""} {
      set new [$w.p.left.list.list get $sel]
      if [file isdirectory [FilePath $new]] {
        set goto $new
      }
    }
  }
  FilePress $w $goto $cmd
  catch {
    $w.p.left.entry delete 0 end
    $w.p.left.entry insert 0 $file(working)
  }
}

#--------------------------------------------------------------------
# FilePress --
#
#	Utility procedure invoked when a mouse button is pressed in
#	the listbox, or when the return key has been pressed when the
#	entry doesn't contain a directory.
#	
# 	Given the name of a file, execute the user command.
#	Given the name of a directory, change the CWD to that
#	directory and redisplay the filebox.
#	The filename and directory name may be specified relative to
#	the CWD, or may be an absolute path name.
#
# w	The iobox.
# sel	The name of either a file or a directory.
# cmd	The command to execute when a file is selected.
#--------------------------------------------------------------------
proc FilePress {w sel cmd} {
  global file
  
  if [string compare $sel ""]==0 {
    return
  }
  set path [FilePath $sel]

  if [file isdirectory $path] {
    set file(cwd) [Fullname $path]
    Browse $w
    return
  }
  set dir [file dirname $path]
  if [file isdirectory $dir] {
    set file(cwd) [Fullname $dir]
    eval $cmd "{$path}"
    return
  }
  error "Unknown file or directory: $sel" "" WARN
  
}

#--------------------------------------------------------------------
# Editname --
#
# 	Utility procedure used by Filebox.  If a single line in the
#	listbox is selected, then display that line in the entry.
#	Otherwise, if 0 or more than 1 line is selected, display
# 	the default string in the entry.
#
# w	The filebox.
#--------------------------------------------------------------------
proc Editname {w} {
  global file

  set sel [$w.p.left.list.list cursel]
  if {$sel != ""} {
    set goto [$w.p.left.list.list get $sel]
    if [file isdirectory $file(cwd)/$goto] {
      set file(working) [$w.p.left.entry get]
      return
    } else {
      set file(working) $goto
    }
  }
  $w.p.left.entry delete 0 end
  $w.p.left.entry insert 0 $file(working)
}
  
#--------------------------------------------------------------------
# Browse --
#
#	Insert the contents of the current working directory (CWD)
#	into a filebox.  Also copy the name of the CWD into the label.
#
# w	The filebox to be filled in with the contents of the cwd.
#--------------------------------------------------------------------
proc Browse {w} {
  global file
  
  set t [winfo toplevel $w]
  set cursor [lindex [$t config -cursor] 4]
  $t config -cursor watch
  if [winfo ismapped $t] {
    update idletasks
  }
  $w.p.cwd configure -text $file(cwd)
  set files [lsort [exec ls $file(cwd)]]
  $w.p.left.list.list delete 0 end
  $w.p.left.list.list yview 0
  $w.p.left.list.list insert end ../
  foreach i $files {
    if [string match .* $i]==0 {
      if [file isdirectory $file(cwd)/$i] {
        append i /
      }
      $w.p.left.list.list insert end $i
    }
  }
  $t config -cursor $cursor
}    


#
# Given a relative path, fill in the absolute part of the path.
# Given an absolute path, return the path.
#
proc FilePath {path} {
  global file

  case [string index $path 0] \
  ~ {return "[file rootname $path][file extension $path]"} \
  / {return $path} \
  default {return $file(cwd)/$path}
}


#--------------------------------------------------------------------
# Dialog --
#
#   Create a new dialog box.
#
# w The name for the new dialog box.
# trans If non-zero, then this is a transient dialog box.
# args  Additional arguments (only for non-transient dialogs).
#   args[0]: The title for the window.
#   args[1]: The icon title for the window.
#   args[2]: The initial geometry of the window.
#--------------------------------------------------------------------
proc Dialog {w trans args} {
  global oldfocus focus

  catch "destroy $w"
  catch "unset oldfocus($w)"
  toplevel $w -class Dialog -bd 0
  wm title $w [lindex $args 0]
#
#  bind $w <Any-FocusIn> "if {\$widget(grab) == \"\"} {focus \$focus($w)}"
#
  if $trans {
    wm protocol $w WM_DELETE_WINDOW Nothing
    wm geometry $w +425+300
    Grab $w
    bind $w <Any-Unmap> {wm deiconify %W; update}
  } else {
    wm iconbitmap $w perspecta
    wm iconname $w [lindex $args 1]
    wm protocol $w WM_DELETE_WINDOW "$w.but.cancel invoke"
    if {[lindex $args 2] != ""} {
      wm geometry $w [lindex $args 2]
    }
    set focus($w) $w
  }
  bind $w <Any-Help> "Help $w"
  bind $w <Any-F1> "Help $w"
}

#--------------------------------------------------------------------
# ScrollBox --
#
#   Make a new paired listbox and vertical scrollbar.
#
# w The name of the "scrollbox".  The listbox is called $w.list,
#   and the scrollbar is called $w.scroll
# geo   The geometry for the listbox.
#--------------------------------------------------------------------
proc ScrollBox {w geo} {
  frame $w
  scrollbar $w.scroll -relief sunken -com "$w.list yview"
  listbox $w.list -relief sunken -yscroll "$w.scroll set" -geometry $geo
  pack $w.scroll -side right -fill y -expand yes -padx 4
  pack $w.list -side left -expand yes -fill x
}

#--------------------------------------------------------------------
# DefaultButton --
#
#   Create a default-style button.  Returns the actual name of
#   the button, which is a button widget buried inside 2 frames
#   to provide the default-style look.
#
# w The name for the default-style button.
# args  Configuration strings for the button widget.
#--------------------------------------------------------------------
proc DefaultButton {w args} {
  frame $w -relief raised -bd 1
  frame $w.0 -relief sunken -bd 1
  eval button $w.0.0 -relief raised -wid 7 -padx 2 -pady 5 $args
  pack append $w $w.0 {left expand padx 4 pady 4}
  pack append $w.0 $w.0.0 {left expand padx 3 pady 3}
  return $w.0.0
}