OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [library/] [tkfboxTest.tcl] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
# tkfbox.tcl --
2
#
3
#       Implements the "TK" standard file selection dialog box. This
4
#       dialog box is used on the Unix platforms whenever the tk_strictMotif
5
#       flag is not set.
6
#
7
#       The "TK" standard file selection dialog box is similar to the
8
#       file selection dialog box on Win95(TM). The user can navigate
9
#       the directories by clicking on the folder icons or by
10
#       selectinf the "Directory" option menu. The user can select
11
#       files by clicking on the file icons or by entering a filename
12
#       in the "Filename:" entry.
13
#
14
# SCCS: @(#) tkfbox.tcl 1.13 97/10/01 14:51:01
15
#
16
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
17
#
18
# See the file "license.terms" for information on usage and redistribution
19
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
20
#
21
 
22
#----------------------------------------------------------------------
23
#
24
#                     I C O N   L I S T
25
#
26
# This is a pseudo-widget that implements the icon list inside the 
27
# tkFDialog dialog box.
28
#
29
#----------------------------------------------------------------------
30
 
31
# tkIconList --
32
#
33
#       Creates an IconList widget.
34
#
35
proc tkIconList {w args} {
36
    upvar #0 $w data
37
 
38
    tkIconList_Config $w $args
39
    tkIconList_Create $w
40
}
41
 
42
# tkIconList_Config --
43
#
44
#       Configure the widget variables of IconList, according to the command
45
#       line arguments.
46
#
47
proc tkIconList_Config {w argList} {
48
    upvar #0 $w data
49
 
50
    # 1: the configuration specs
51
    #
52
    set specs {
53
        {-browsecmd "" "" ""}
54
        {-command "" "" ""}
55
        {-multiple "" "" "0"}
56
    }
57
 
58
    # 2: parse the arguments
59
    #
60
    tclParseConfigSpec $w $specs "" $argList
61
}
62
 
63
# tkIconList_Create --
64
#
65
#       Creates an IconList widget by assembling a canvas widget and a
66
#       scrollbar widget. Sets all the bindings necessary for the IconList's
67
#       operations.
68
#
69
proc tkIconList_Create {w} {
70
    upvar #0 $w data
71
 
72
    frame $w
73
    set data(sbar)   [scrollbar $w.sbar -orient horizontal \
74
        -highlightthickness 0 -takefocus 0]
75
    set data(canvas) [canvas $w.canvas -bd 2 -relief sunken \
76
        -width 400 -height 120 -takefocus 1]
77
    pack $data(sbar) -side bottom -fill x -padx 2
78
    pack $data(canvas) -expand yes -fill both
79
 
80
    $data(sbar) config -command "$data(canvas) xview"
81
    $data(canvas) config -xscrollcommand "$data(sbar) set"
82
 
83
    # Initializes the max icon/text width and height and other variables
84
    #
85
    set data(maxIW) 1
86
    set data(maxIH) 1
87
    set data(maxTW) 1
88
    set data(maxTH) 1
89
    set data(numItems) 0
90
    set data(curItem)  {}
91
    set data(noScroll) 1
92
 
93
    # Creates the event bindings.
94
    #
95
    bind $data(canvas) <Configure> "tkIconList_Arrange $w"
96
 
97
    bind $data(canvas) <1>         "tkIconList_Btn1 $w %x %y"
98
    bind $data(canvas) <B1-Motion> "tkIconList_Motion1 $w %x %y"
99
    bind $data(canvas) <Shift-1>   "tkIconList_ShiftBtn1 $w %x %y"
100
    bind $data(canvas) <Double-1>  "tkIconList_Double1 $w %x %y"
101
    bind $data(canvas) <ButtonRelease-1> "tkCancelRepeat"
102
    bind $data(canvas) <B1-Leave>  "tkIconList_Leave1 $w %x %y"
103
    bind $data(canvas) <B1-Enter>  "tkCancelRepeat"
104
 
105
    bind $data(canvas) <Up>        "tkIconList_UpDown $w -1"
106
    bind $data(canvas) <Down>      "tkIconList_UpDown $w  1"
107
    bind $data(canvas) <Left>      "tkIconList_LeftRight $w -1"
108
    bind $data(canvas) <Right>     "tkIconList_LeftRight $w  1"
109
    bind $data(canvas) <Return>    "tkIconList_ReturnKey $w"
110
    bind $data(canvas) <KeyPress>  "tkIconList_KeyPress $w %A"
111
    bind $data(canvas) <Control-KeyPress> ";"
112
    bind $data(canvas) <Alt-KeyPress>  ";"
113
 
114
    bind $data(canvas) <FocusIn>   "tkIconList_FocusIn $w"
115
 
116
    return $w
117
}
118
 
119
# tkIconList_AutoScan --
120
#
121
# This procedure is invoked when the mouse leaves an entry window
122
# with button 1 down.  It scrolls the window up, down, left, or
123
# right, depending on where the mouse left the window, and reschedules
124
# itself as an "after" command so that the window continues to scroll until
125
# the mouse moves back into the window or the mouse button is released.
126
#
127
# Arguments:
128
# w -           The IconList window.
129
#
130
proc tkIconList_AutoScan {w} {
131
    upvar #0 $w data
132
    global tkPriv
133
 
134
    if {![winfo exists $w]} return
135
    set x $tkPriv(x)
136
    set y $tkPriv(y)
137
 
138
    if {$data(noScroll)} {
139
        return
140
    }
141
    if {$x >= [winfo width $data(canvas)]} {
142
        $data(canvas) xview scroll 1 units
143
    } elseif {$x < 0} {
144
        $data(canvas) xview scroll -1 units
145
    } elseif {$y >= [winfo height $data(canvas)]} {
146
        # do nothing
147
    } elseif {$y < 0} {
148
        # do nothing
149
    } else {
150
        return
151
    }
152
 
153
    tkIconList_Motion1 $w $x $y
154
    set tkPriv(afterId) [after 50 tkIconList_AutoScan $w]
155
}
156
 
157
# Deletes all the items inside the canvas subwidget and reset the IconList's
158
# state.
159
#
160
proc tkIconList_DeleteAll {w} {
161
    upvar #0 $w data
162
    upvar #0 $w:itemList itemList
163
 
164
    $data(canvas) delete all
165
    catch {unset data(selected)}
166
    catch {unset data(rect)}
167
    catch {unset data(list)}
168
    catch {unset itemList}
169
    set data(maxIW) 1
170
    set data(maxIH) 1
171
    set data(maxTW) 1
172
    set data(maxTH) 1
173
    set data(numItems) 0
174
    set data(curItem)  {}
175
    set data(noScroll) 1
176
    $data(sbar) set 0.0 1.0
177
    $data(canvas) xview moveto 0
178
}
179
 
180
# Adds an icon into the IconList with the designated image and text
181
#
182
proc tkIconList_Add {w image text} {
183
    upvar #0 $w data
184
    upvar #0 $w:itemList itemList
185
    upvar #0 $w:textList textList
186
 
187
    set iTag [$data(canvas) create image 0 0 -image $image -anchor nw]
188
    set tTag [$data(canvas) create text  0 0 -text  $text  -anchor nw \
189
        -font $data(font)]
190
    set rTag [$data(canvas) create rect  0 0 0 0 -fill "" -outline ""]
191
 
192
    set b [$data(canvas) bbox $iTag]
193
    set iW [expr {[lindex $b 2]-[lindex $b 0]}]
194
    set iH [expr {[lindex $b 3]-[lindex $b 1]}]
195
    if {$data(maxIW) < $iW} {
196
        set data(maxIW) $iW
197
    }
198
    if {$data(maxIH) < $iH} {
199
        set data(maxIH) $iH
200
    }
201
 
202
    set b [$data(canvas) bbox $tTag]
203
    set tW [expr {[lindex $b 2]-[lindex $b 0]}]
204
    set tH [expr {[lindex $b 3]-[lindex $b 1]}]
205
    if {$data(maxTW) < $tW} {
206
        set data(maxTW) $tW
207
    }
208
    if {$data(maxTH) < $tH} {
209
        set data(maxTH) $tH
210
    }
211
 
212
    lappend data(list) [list $iTag $tTag $rTag $iW $iH $tW $tH $data(numItems)]
213
    set itemList($rTag) [list $iTag $tTag $text $data(numItems)]
214
    set textList($data(numItems)) [string tolower $text]
215
    incr data(numItems)
216
}
217
 
218
# Places the icons in a column-major arrangement.
219
#
220
proc tkIconList_Arrange {w} {
221
    upvar #0 $w data
222
 
223
    if {![info exists data(list)]} {
224
        if {[info exists data(canvas)] && [winfo exists $data(canvas)]} {
225
            set data(noScroll) 1
226
            $data(sbar) config -command ""
227
        }
228
        return
229
    }
230
 
231
    set W [winfo width  $data(canvas)]
232
    set H [winfo height $data(canvas)]
233
    set pad [expr {[$data(canvas) cget -highlightthickness] + \
234
            [$data(canvas) cget -bd]}]
235
    if {$pad < 2} {
236
        set pad 2
237
    }
238
 
239
    incr W -[expr {$pad*2}]
240
    incr H -[expr {$pad*2}]
241
 
242
    set dx [expr {$data(maxIW) + $data(maxTW) + 8}]
243
    if {$data(maxTH) > $data(maxIH)} {
244
        set dy $data(maxTH)
245
    } else {
246
        set dy $data(maxIH)
247
    }
248
    incr dy 2
249
    set shift [expr {$data(maxIW) + 4}]
250
 
251
    set x [expr {$pad * 2}]
252
    set y [expr {$pad * 1}] ; # Why * 1 ?
253
    set usedColumn 0
254
    foreach sublist $data(list) {
255
        set usedColumn 1
256
        set iTag [lindex $sublist 0]
257
        set tTag [lindex $sublist 1]
258
        set rTag [lindex $sublist 2]
259
        set iW   [lindex $sublist 3]
260
        set iH   [lindex $sublist 4]
261
        set tW   [lindex $sublist 5]
262
        set tH   [lindex $sublist 6]
263
 
264
        set i_dy [expr {($dy - $iH)/2}]
265
        set t_dy [expr {($dy - $tH)/2}]
266
 
267
        $data(canvas) coords $iTag $x                    [expr {$y + $i_dy}]
268
        $data(canvas) coords $tTag [expr {$x + $shift}]  [expr {$y + $t_dy}]
269
        $data(canvas) coords $tTag [expr {$x + $shift}]  [expr {$y + $t_dy}]
270
        $data(canvas) coords $rTag $x $y [expr {$x+$dx}] [expr {$y+$dy}]
271
 
272
        incr y $dy
273
        if {($y + $dy) > $H} {
274
            set y [expr {$pad * 1}] ; # *1 ?
275
            incr x $dx
276
            set usedColumn 0
277
        }
278
    }
279
 
280
    if {$usedColumn} {
281
        set sW [expr {$x + $dx}]
282
    } else {
283
        set sW $x
284
    }
285
 
286
    if {$sW < $W} {
287
        $data(canvas) config -scrollregion "$pad $pad $sW $H"
288
        $data(sbar) config -command ""
289
        $data(canvas) xview moveto 0
290
        set data(noScroll) 1
291
    } else {
292
        $data(canvas) config -scrollregion "$pad $pad $sW $H"
293
        $data(sbar) config -command "$data(canvas) xview"
294
        set data(noScroll) 0
295
    }
296
 
297
    set data(itemsPerColumn) [expr {($H-$pad)/$dy}]
298
    if {$data(itemsPerColumn) < 1} {
299
        set data(itemsPerColumn) 1
300
    }
301
 
302
    if {$data(curItem) != {}} {
303
        tkIconList_Select $w [lindex [lindex $data(list) $data(curItem)] 2] 0
304
    }
305
}
306
 
307
# Gets called when the user invokes the IconList (usually by double-clicking
308
# or pressing the Return key).
309
#
310
proc tkIconList_Invoke {w} {
311
    upvar #0 $w data
312
 
313
    if {[string compare $data(-command) ""] && [info exists data(selected)]} {
314
        eval $data(-command)
315
    }
316
}
317
 
318
# tkIconList_See --
319
#
320
#       If the item is not (completely) visible, scroll the canvas so that
321
#       it becomes visible.
322
proc tkIconList_See {w rTag} {
323
    upvar #0 $w data
324
    upvar #0 $w:itemList itemList
325
 
326
    if {$data(noScroll)} {
327
        return
328
    }
329
    set sRegion [$data(canvas) cget -scrollregion]
330
    if {![string compare $sRegion {}]} {
331
        return
332
    }
333
 
334
    if {![info exists itemList($rTag)]} {
335
        return
336
    }
337
 
338
 
339
    set bbox [$data(canvas) bbox $rTag]
340
    set pad [expr {[$data(canvas) cget -highlightthickness] + \
341
            [$data(canvas) cget -bd]}]
342
 
343
    set x1 [lindex $bbox 0]
344
    set x2 [lindex $bbox 2]
345
    incr x1 -[expr {$pad * 2}]
346
    incr x2 -[expr {$pad * 1}] ; # *1 ?
347
 
348
    set cW [expr {[winfo width $data(canvas)] - $pad*2}]
349
 
350
    set scrollW [expr {[lindex $sRegion 2]-[lindex $sRegion 0]+1}]
351
    set dispX [expr {int([lindex [$data(canvas) xview] 0]*$scrollW)}]
352
    set oldDispX $dispX
353
 
354
    # check if out of the right edge
355
    #
356
    if {($x2 - $dispX) >= $cW} {
357
        set dispX [expr {$x2 - $cW}]
358
    }
359
    # check if out of the left edge
360
    #
361
    if {($x1 - $dispX) < 0} {
362
        set dispX $x1
363
    }
364
 
365
    if {$oldDispX != $dispX} {
366
        set fraction [expr {double($dispX)/double($scrollW)}]
367
        $data(canvas) xview moveto $fraction
368
    }
369
}
370
 
371
proc tkIconList_SelectAtXY {w x y} {
372
    upvar #0 $w data
373
 
374
    tkIconList_Select $w [$data(canvas) find closest \
375
        [$data(canvas) canvasx $x] [$data(canvas) canvasy $y]]
376
}
377
 
378
proc tkIconList_AddSelectAtXY {w x y {no_delete 0}} {
379
    upvar #0 $w data
380
 
381
    if {$data(-multiple) && [info exists data(selected)]} {
382
        tkIconList_AddSelect $w [$data(canvas) find closest \
383
                [$data(canvas) canvasx $x] [$data(canvas) canvasy $y]] \
384
                1 $no_delete
385
        return
386
    }
387
    tkIconList_SelectAtXY $w $x $y
388
}
389
 
390
proc tkIconList_Select {w rTag {callBrowse 1}} {
391
    upvar #0 $w data
392
    upvar #0 $w:itemList itemList
393
 
394
    if {![info exists itemList($rTag)]} {
395
        return
396
    }
397
    set iTag   [lindex $itemList($rTag) 0]
398
    set tTag   [lindex $itemList($rTag) 1]
399
    set text   [lindex $itemList($rTag) 2]
400
    set serial [lindex $itemList($rTag) 3]
401
 
402
    if {$data(-multiple) && [info exists data(rect)]} {
403
        foreach r $data(rect) {
404
            $data(canvas) delete $r
405
        }
406
        unset data(rect)
407
    }
408
    if ![info exists data(rect)] {
409
 
410
        set data(rect) [$data(canvas) create rect 0 0 0 0 \
411
            -fill #a0a0ff -outline #a0a0ff]
412
    }
413
    $data(canvas) lower $data(rect)
414
    set bbox [$data(canvas) bbox $tTag]
415
    eval $data(canvas) coords $data(rect) $bbox
416
 
417
    set data(curItem) $serial
418
 
419
    #we can't set the text to data(selected) as text, this is bugy,
420
    #when the path contains blanks
421
    if {$data(-multiple)} {
422
        catch {unset data(selected)}
423
        lappend data(selected) $text
424
    } else {
425
        set data(selected) $text
426
    }
427
 
428
    if {$callBrowse} {
429
        if [string compare $data(-browsecmd) ""] {
430
            eval $data(-browsecmd) [list $data(selected)]
431
        }
432
    }
433
}
434
 
435
proc tkIconList_AddSelect {w rTag {callBrowse 1} {no_delete 0}} {
436
    upvar #0 $w data
437
    upvar #0 $w:itemList itemList
438
 
439
    if ![info exists itemList($rTag)] {
440
        return
441
    }
442
    set iTag   [lindex $itemList($rTag) 0]
443
    set tTag   [lindex $itemList($rTag) 1]
444
    set text   [lindex $itemList($rTag) 2]
445
    set serial [lindex $itemList($rTag) 3]
446
 
447
    if {[lsearch -exact $data(selected) $text] != -1} {
448
        if {$no_delete} {
449
            return
450
        }
451
 
452
        # we've clicked on an existing item, so we need to remove it
453
        set i [lsearch -exact $data(selected) $text]
454
        set data(selected) [lreplace $data(selected) $i $i]
455
 
456
        # find the appropriate coordinates and remove the
457
        # corresponding rectangle.
458
        set tmpbbox [$data(canvas) bbox $tTag]
459
        for {set i 0} {$i<[llength $data(rect)]} {incr i} {
460
            set rectTag [lindex $data(rect) $i]
461
            set testbbox [$data(canvas) coords $rectTag]
462
            # test first two coordinates; if they're the same the
463
            # entire box should match
464
            if {[lindex $testbbox 0]==[lindex $tmpbbox 0] && \
465
                    [lindex $testbbox 1]==[lindex $tmpbbox 1]} {
466
                $data(canvas) delete $rectTag
467
                set data(rect) [lreplace $data(rect) $i $i]
468
                break
469
            }
470
        }
471
 
472
        if {$callBrowse} {
473
            if [string compare $data(-browsecmd) ""] {
474
                eval $data(-browsecmd) [list $data(selected)]
475
            }
476
        }
477
        return
478
    }
479
 
480
    set tmprect [$data(canvas) create rect 0 0 0 0 \
481
            -fill #a0a0ff -outline #a0a0ff]
482
    lappend data(rect) $tmprect
483
 
484
    $data(canvas) lower $tmprect
485
    set bbox [$data(canvas) bbox $tTag]
486
    eval $data(canvas) coords $tmprect $bbox
487
 
488
    set data(curItem) $serial
489
    lappend data(selected) $text
490
 
491
    if {$callBrowse} {
492
        if [string compare $data(-browsecmd) ""] {
493
            eval $data(-browsecmd) [list $data(selected)]
494
        }
495
    }
496
}
497
 
498
proc tkIconList_Unselect {w} {
499
    upvar #0 $w data
500
 
501
    if [info exists data(rect)] {
502
        foreach r $data(rect) {
503
            $data(canvas) delete $r
504
        }
505
        unset data(rect)
506
    }
507
    if {[info exists data(selected)]} {
508
        unset data(selected)
509
    }
510
    set data(curItem)  {}
511
}
512
 
513
# Returns the selected item
514
#
515
proc tkIconList_Get {w} {
516
    upvar #0 $w data
517
 
518
    if {[info exists data(selected)]} {
519
        return $data(selected)
520
    } else {
521
        return ""
522
    }
523
}
524
 
525
 
526
proc tkIconList_Btn1 {w x y} {
527
    upvar #0 $w data
528
 
529
    focus $data(canvas)
530
    tkIconList_SelectAtXY $w $x $y
531
}
532
 
533
proc tkIconList_ShiftBtn1 {w x y} {
534
    upvar #0 $w data
535
 
536
    focus $data(canvas)
537
    tkIconList_AddSelectAtXY $w $x $y
538
}
539
 
540
# Gets called on button-1 motions
541
#
542
proc tkIconList_Motion1 {w x y} {
543
    global tkPriv
544
    set tkPriv(x) $x
545
    set tkPriv(y) $y
546
 
547
    tkIconList_AddSelectAtXY $w $x $y 1
548
}
549
 
550
proc tkIconList_Double1 {w x y} {
551
    upvar #0 $w data
552
 
553
    if {$data(curItem) != {}} {
554
        tkIconList_Invoke $w
555
    }
556
}
557
 
558
proc tkIconList_ReturnKey {w} {
559
    tkIconList_Invoke $w
560
}
561
 
562
proc tkIconList_Leave1 {w x y} {
563
    global tkPriv
564
 
565
    set tkPriv(x) $x
566
    set tkPriv(y) $y
567
    tkIconList_AutoScan $w
568
}
569
 
570
proc tkIconList_FocusIn {w} {
571
    upvar #0 $w data
572
 
573
    if {![info exists data(list)]} {
574
        return
575
    }
576
 
577
    if {$data(curItem) == {}} {
578
        set rTag [lindex [lindex $data(list) 0] 2]
579
        tkIconList_Select $w $rTag
580
    }
581
}
582
 
583
# tkIconList_UpDown --
584
#
585
# Moves the active element up or down by one element
586
#
587
# Arguments:
588
# w -           The IconList widget.
589
# amount -      +1 to move down one item, -1 to move back one item.
590
#
591
proc tkIconList_UpDown {w amount} {
592
    upvar #0 $w data
593
 
594
    if {![info exists data(list)]} {
595
        return
596
    }
597
 
598
    if {$data(curItem) == {}} {
599
        set rTag [lindex [lindex $data(list) 0] 2]
600
    } else {
601
        set oldRTag [lindex [lindex $data(list) $data(curItem)] 2]
602
        set rTag [lindex [lindex $data(list) [expr {$data(curItem)+$amount}]] 2]
603
        if {![string compare $rTag ""]} {
604
            set rTag $oldRTag
605
        }
606
    }
607
 
608
    if {[string compare $rTag ""]} {
609
        tkIconList_Select $w $rTag
610
        tkIconList_See $w $rTag
611
    }
612
}
613
 
614
# tkIconList_LeftRight --
615
#
616
# Moves the active element left or right by one column
617
#
618
# Arguments:
619
# w -           The IconList widget.
620
# amount -      +1 to move right one column, -1 to move left one column.
621
#
622
proc tkIconList_LeftRight {w amount} {
623
    upvar #0 $w data
624
 
625
    if {![info exists data(list)]} {
626
        return
627
    }
628
    if {$data(curItem) == {}} {
629
        set rTag [lindex [lindex $data(list) 0] 2]
630
    } else {
631
        set oldRTag [lindex [lindex $data(list) $data(curItem)] 2]
632
        set newItem [expr {$data(curItem)+($amount*$data(itemsPerColumn))}]
633
        set rTag [lindex [lindex $data(list) $newItem] 2]
634
        if {![string compare $rTag ""]} {
635
            set rTag $oldRTag
636
        }
637
    }
638
 
639
    if {[string compare $rTag ""]} {
640
        tkIconList_Select $w $rTag
641
        tkIconList_See $w $rTag
642
    }
643
}
644
 
645
#----------------------------------------------------------------------
646
#               Accelerator key bindings
647
#----------------------------------------------------------------------
648
 
649
# tkIconList_KeyPress --
650
#
651
#       Gets called when user enters an arbitrary key in the listbox.
652
#
653
proc tkIconList_KeyPress {w key} {
654
    global tkPriv
655
 
656
    append tkPriv(ILAccel,$w) $key
657
    tkIconList_Goto $w $tkPriv(ILAccel,$w)
658
    catch {
659
        after cancel $tkPriv(ILAccel,$w,afterId)
660
    }
661
    set tkPriv(ILAccel,$w,afterId) [after 500 tkIconList_Reset $w]
662
}
663
 
664
proc tkIconList_Goto {w text} {
665
    upvar #0 $w data
666
    upvar #0 $w:textList textList
667
    global tkPriv
668
 
669
    if {![info exists data(list)]} {
670
        return
671
    }
672
 
673
    if {[string length $text] == 0} {
674
        return
675
    }
676
 
677
    if {$data(curItem) == {} || $data(curItem) == 0} {
678
        set start  0
679
    } else {
680
        set start  $data(curItem)
681
    }
682
 
683
    set text [string tolower $text]
684
    set theIndex -1
685
    set less 0
686
    set len [string length $text]
687
    set len0 [expr {$len-1}]
688
    set i $start
689
 
690
    # Search forward until we find a filename whose prefix is an exact match
691
    # with $text
692
    while 1 {
693
        set sub [string range $textList($i) 0 $len0]
694
        if {[string compare $text $sub] == 0} {
695
            set theIndex $i
696
            break
697
        }
698
        incr i
699
        if {$i == $data(numItems)} {
700
            set i 0
701
        }
702
        if {$i == $start} {
703
            break
704
        }
705
    }
706
 
707
    if {$theIndex > -1} {
708
        set rTag [lindex [lindex $data(list) $theIndex] 2]
709
        tkIconList_Select $w $rTag 0
710
        tkIconList_See $w $rTag
711
    }
712
}
713
 
714
proc tkIconList_Reset {w} {
715
    global tkPriv
716
 
717
    catch {unset tkPriv(ILAccel,$w)}
718
}
719
 
720
#----------------------------------------------------------------------
721
#
722
#                     F I L E   D I A L O G
723
#
724
#----------------------------------------------------------------------
725
 
726
# tkFDialog --
727
#
728
#       Implements the TK file selection dialog. This dialog is used when
729
#       the tk_strictMotif flag is set to false. This procedure shouldn't
730
#       be called directly. Call tk_getOpenFile or tk_getSaveFile instead.
731
#
732
proc tkFDialog {args} {
733
    global tkPriv
734
    global __old_dialog
735
    global __old_multiple
736
    set w __tk_filedialog
737
    upvar #0 $w data
738
 
739
    if {![string compare [lindex [info level 0] 0] tk_getOpenFile]} {
740
        set type open
741
    } else {
742
        set type save
743
    }
744
 
745
    tkFDialog_Config $w $type $args
746
 
747
    if {![string compare $data(-parent) .]} {
748
        set w .$w
749
    } else {
750
        set w $data(-parent).$w
751
    }
752
 
753
    #because tk doesn't use window-path dependent array, it is
754
    #impossible to use more than one dialog box at the same time,
755
    #so we have to recreate the dialog!
756
    if {[info exists __old_dialog] \
757
        && ($__old_dialog != $w || $__old_multiple != $data(-multiple))} {
758
        catch {destroy $w}
759
        catch {destroy $__old_dialog}
760
    }
761
    set __old_dialog $w
762
    set __old_multiple $data(-multiple)
763
 
764
    # (re)create the dialog box if necessary
765
    #
766
    set new_dialog 0
767
    if {![winfo exists $w]} {
768
        tkFDialog_Create $w
769
        set new_dialog 1
770
    } elseif {[string compare [winfo class $w] TkFDialog]} {
771
        destroy $w
772
        tkFDialog_Create $w
773
        set new_dialog 1
774
    } else {
775
        set data(dirMenuBtn) $w.f1.menu
776
        set data(dirMenu) $w.f1.menu.menu
777
        set data(upBtn) $w.f1.up
778
        set data(icons) $w.icons
779
        set data(ent) $w.f2.ent
780
        set data(typeMenuLab) $w.f3.lab
781
        set data(typeMenuBtn) $w.f3.menu
782
        set data(typeMenu) $data(typeMenuBtn).m
783
        set data(okBtn) $w.f2.ok
784
        set data(cancelBtn) $w.f3.cancel
785
    }
786
    wm transient $w $data(-parent)
787
    #trace variable
788
    trace variable data(selectPath) w "tkFDialog_SetPath $w"
789
 
790
    # 5. Initialize the file types menu
791
    #
792
    if {$data(-filetypes) != {}} {
793
        $data(typeMenu) delete 0 end
794
        foreach type $data(-filetypes) {
795
            set title  [lindex $type 0]
796
            set filter [lindex $type 1]
797
            $data(typeMenu) add command -label $title \
798
                -command [list tkFDialog_SetFilter $w $type]
799
        }
800
        tkFDialog_SetFilter $w [lindex $data(-filetypes) 0]
801
        $data(typeMenuBtn) config -state normal
802
        $data(typeMenuLab) config -state normal
803
    } else {
804
        set data(filter) "*"
805
        $data(typeMenuBtn) config -state disabled -takefocus 0
806
        $data(typeMenuLab) config -state disabled
807
    }
808
 
809
    tkFDialog_UpdateWhenIdle $w
810
 
811
    # 6. Withdraw the window, then update all the geometry information
812
    # so we know how big it wants to be, then center the window in the
813
    # display and de-iconify it.
814
 
815
    if {$new_dialog} {
816
        #center dialog, when it has been new created
817
        wm withdraw $w
818
        update idletasks
819
        set x [expr {[winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
820
                       - [winfo vrootx [winfo parent $w]]}]
821
        set y [expr {[winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
822
            - [winfo vrooty [winfo parent $w]]}]
823
        wm geom $w [winfo reqwidth $w]x[winfo reqheight $w]+$x+$y
824
    }
825
    wm title $w $data(-title)
826
    wm deiconify $w
827
 
828
    # 7. Set a grab and claim the focus too.
829
 
830
    set oldFocus [focus]
831
    set oldGrab [grab current $w]
832
    if {$oldGrab != ""} {
833
        set grabStatus [grab status $oldGrab]
834
    }
835
    grab $w
836
    focus $data(ent)
837
    $data(ent) delete 0 end
838
    $data(ent) insert 0 $data(selectFile)
839
    $data(ent) select from 0
840
    $data(ent) select to   end
841
    $data(ent) icursor end
842
 
843
    # 8. Wait for the user to respond, then restore the focus and
844
    # return the index of the selected button.  Restore the focus
845
    # before deleting the window, since otherwise the window manager
846
    # may take the focus away so we can't redirect it.  Finally,
847
    # restore any grab that was in effect.
848
 
849
    tkwait variable tkPriv(selectFilePath)
850
    catch {focus $oldFocus}
851
    grab release $w
852
    wm withdraw $w
853
    if {$oldGrab != ""} {
854
        if {$grabStatus == "global"} {
855
            grab -global $oldGrab
856
        } else {
857
            grab $oldGrab
858
        }
859
    }
860
    #delete the tracer, because this conflicts with multiple
861
    #used dialogs
862
    trace vdelete data(selectPath) w "tkFDialog_SetPath $w"
863
    return $tkPriv(selectFilePath)
864
}
865
 
866
# tkFDialog_Config --
867
#
868
#       Configures the TK filedialog according to the argument list
869
#
870
proc tkFDialog_Config {w type argList} {
871
    upvar #0 $w data
872
 
873
    set data(type) $type
874
 
875
    # 1: the configuration specs
876
    #
877
    set specs {
878
        {-defaultextension "" "" ""}
879
        {-filetypes "" "" ""}
880
        {-initialdir "" "" ""}
881
        {-initialfile "" "" ""}
882
        {-parent "" "" "."}
883
        {-title "" "" ""}
884
    }
885
    if ![string compare $type open] {
886
        # CYGNUS LOCAL: Handle -choosedir.
887
        # Note: the -choosedir option is a Cygnus extension.  It is not
888
        # documented since it only works on Unix -- it is an
889
        # implementation detail of the directory-choosing code in
890
        # in libgui.
891
        lappend specs {-multiple "" "" "0"} {-choosedir "" "" "0"}
892
        # END CYGNUS LOCAL
893
    }
894
 
895
    # 2: default values depending on the type of the dialog
896
    #
897
    if {![info exists data(selectPath)]} {
898
        # first time the dialog has been popped up
899
        set data(selectPath) [pwd]
900
        set data(selectFile) ""
901
    }
902
 
903
    # 3: parse the arguments
904
    #
905
    tclParseConfigSpec $w $specs "" $argList
906
 
907
    if {![string compare $data(-title) ""]} {
908
        if {![string compare $type "open"]} {
909
            set data(-title) "Open"
910
        } else {
911
            set data(-title) "Save As"
912
        }
913
    }
914
 
915
    # 4: set the default directory and selection according to the -initial
916
    #    settings
917
    #
918
    # Khamis 16-04-98
919
    # When the path contains blanks, glob returns an item in a list, but
920
    # data(selectPath) must be an item and not a list of items, so we
921
    # must extract the item from the returned list.
922
    if {[string compare $data(-initialdir) ""]} {
923
        if {[file isdirectory $data(-initialdir)]} {
924
            #khamis: Join result of glob to an item
925
            set data(selectPath) [lindex [glob $data(-initialdir)] 0]
926
        } else {
927
            set data(selectPath) [pwd]
928
        }
929
 
930
        # Convert the initialdir to an absolute path name.
931
 
932
        set old [pwd]
933
        cd $data(selectPath)
934
        set data(selectPath) [pwd]
935
        cd $old
936
    }
937
    set data(selectFile) $data(-initialfile)
938
 
939
    # 5. Parse the -filetypes option
940
    #
941
    set data(-filetypes) [tkFDGetFileTypes $data(-filetypes)]
942
 
943
    if {![winfo exists $data(-parent)]} {
944
        error "bad window path name \"$data(-parent)\""
945
    }
946
 
947
    # Set -multiple to a one or zero value (not other boolean types
948
    # like "yes") so we can use it in tests easier.
949
    if {![string compare $type save]} {
950
        set data(-multiple) 0
951
        # CYGNUS LOCAL: choosedir
952
        # Handle -choosedir here as well.
953
        set data(-choosedir) 0
954
        # END CYGNUS LOCAL
955
    } else {
956
        if {$data(-multiple)} {
957
            set data(-multiple) 1
958
        }
959
    }
960
}
961
 
962
proc tkFDialog_Create {w} {
963
    set dataName [lindex [split $w .] end]
964
    upvar #0 $dataName data
965
    global tk_library
966
 
967
    toplevel $w -class TkFDialog
968
 
969
    # f1: the frame with the directory option menu
970
    #
971
    set f1 [frame $w.f1]
972
    label $f1.lab -text "Directory:" -under 0
973
    set data(dirMenuBtn) $f1.menu
974
    set data(dirMenu) [tk_optionMenu $f1.menu [format %s(selectPath) $dataName] ""]
975
    set data(upBtn) [button $f1.up]
976
    if {![info exists tkPriv(updirImage)]} {
977
        set tkPriv(updirImage) [image create bitmap -data {
978
#define updir_width 28
979
#define updir_height 16
980
static char updir_bits[] = {
981
   0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00,
982
   0x20, 0x40, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x01, 0x10, 0x00, 0x00, 0x01,
983
   0x10, 0x02, 0x00, 0x01, 0x10, 0x07, 0x00, 0x01, 0x90, 0x0f, 0x00, 0x01,
984
   0x10, 0x02, 0x00, 0x01, 0x10, 0x02, 0x00, 0x01, 0x10, 0x02, 0x00, 0x01,
985
   0x10, 0xfe, 0x07, 0x01, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x01,
986
   0xf0, 0xff, 0xff, 0x01};}]
987
    }
988
    $data(upBtn) config -image $tkPriv(updirImage)
989
 
990
    $f1.menu config -takefocus 1 -highlightthickness 2
991
 
992
    pack $data(upBtn) -side right -padx 4 -fill both
993
    pack $f1.lab -side left -padx 4 -fill both
994
    pack $f1.menu -expand yes -fill both -padx 4
995
 
996
    # data(icons): the IconList that list the files and directories.
997
    #
998
    set data(icons) [tkIconList $w.icons \
999
        -browsecmd "tkFDialog_ListBrowse $w" \
1000
        -command   "tkFDialog_ListInvoke $w" \
1001
        -multiple  "$data(-multiple)"]
1002
 
1003
    # f2: the frame with the OK button and the "file name" field
1004
    #
1005
    set f2 [frame $w.f2 -bd 0]
1006
    label $f2.lab -text "File name:" -anchor e -width 14 -under 5 -pady 0
1007
    if {$data(-multiple)} {
1008
        $f2.lab config -text "File names:"
1009
    }
1010
    set data(ent) [entry $f2.ent]
1011
 
1012
    # The font to use for the icons. The default Canvas font on Unix
1013
    # is just deviant.
1014
    global $w.icons
1015
    set $w.icons(font) [$data(ent) cget -font]
1016
 
1017
    # f3: the frame with the cancel button and the file types field
1018
    #
1019
    set f3 [frame $w.f3 -bd 0]
1020
 
1021
    # The "File of types:" label needs to be grayed-out when
1022
    # -filetypes are not specified. The label widget does not support
1023
    # grayed-out text on monochrome displays. Therefore, we have to
1024
    # use a button widget to emulate a label widget (by setting its
1025
    # bindtags)
1026
 
1027
    set data(typeMenuLab) [button $f3.lab -text "Files of type:" \
1028
        -anchor e -width 14 -under 9 \
1029
        -bd [$f2.lab cget -bd] \
1030
        -highlightthickness [$f2.lab cget -highlightthickness] \
1031
        -relief [$f2.lab cget -relief] \
1032
        -padx [$f2.lab cget -padx] \
1033
        -pady [$f2.lab cget -pady]]
1034
    bindtags $data(typeMenuLab) [list $data(typeMenuLab) Label \
1035
            [winfo toplevel $data(typeMenuLab)] all]
1036
 
1037
    set data(typeMenuBtn) [menubutton $f3.menu -indicatoron 1 -menu $f3.menu.m]
1038
    set data(typeMenu) [menu $data(typeMenuBtn).m -tearoff 0]
1039
    $data(typeMenuBtn) config -takefocus 1 -highlightthickness 2 \
1040
        -relief raised -bd 2 -anchor w
1041
 
1042
    # the okBtn is created after the typeMenu so that the keyboard traversal
1043
    # is in the right order
1044
    set data(okBtn)     [button $f2.ok     -text OK     -under 0 -width 6 \
1045
        -default active -pady 3]
1046
    set data(cancelBtn) [button $f3.cancel -text Cancel -under 0 -width 6\
1047
        -default normal -pady 3]
1048
 
1049
    # pack the widgets in f2 and f3
1050
    #
1051
    pack $data(okBtn) -side right -padx 4 -anchor e
1052
    pack $f2.lab -side left -padx 4
1053
    pack $f2.ent -expand yes -fill x -padx 2 -pady 0
1054
 
1055
    pack $data(cancelBtn) -side right -padx 4 -anchor w
1056
    pack $data(typeMenuLab) -side left -padx 4
1057
    pack $data(typeMenuBtn) -expand yes -fill x -side right
1058
 
1059
    # Pack all the frames together. We are done with widget construction.
1060
    #
1061
    pack $f1 -side top -fill x -pady 4
1062
    pack $f3 -side bottom -fill x
1063
    pack $f2 -side bottom -fill x
1064
    pack $data(icons) -expand yes -fill both -padx 4 -pady 1
1065
 
1066
    # Set up the event handlers
1067
    #
1068
    bind $data(ent) <Return>  "tkFDialog_ActivateEnt $w"
1069
 
1070
    $data(upBtn)     config -command "tkFDialog_UpDirCmd $w"
1071
    $data(okBtn)     config -command "tkFDialog_OkCmd $w"
1072
    $data(cancelBtn) config -command "tkFDialog_CancelCmd $w"
1073
 
1074
    #trace variable data(selectPath) w "tkFDialog_SetPath $w"
1075
 
1076
    bind $w <Alt-d> "focus $data(dirMenuBtn)"
1077
    bind $w <Alt-t> [format {
1078
        if {"[%s cget -state]" == "normal"} {
1079
            focus %s
1080
        }
1081
    } $data(typeMenuBtn) $data(typeMenuBtn)]
1082
    bind $w <Alt-n> "focus $data(ent)"
1083
    bind $w <KeyPress-Escape> "tkButtonInvoke $data(cancelBtn)"
1084
    bind $w <Alt-c> "tkButtonInvoke $data(cancelBtn)"
1085
    bind $w <Alt-o> "tkFDialog_InvokeBtn $w Open"
1086
    bind $w <Alt-s> "tkFDialog_InvokeBtn $w Save"
1087
 
1088
    wm protocol $w WM_DELETE_WINDOW "tkFDialog_CancelCmd $w"
1089
 
1090
    # Build the focus group for all the entries
1091
    #
1092
    tkFocusGroup_Create $w
1093
    tkFocusGroup_BindIn $w  $data(ent) "tkFDialog_EntFocusIn $w"
1094
    tkFocusGroup_BindOut $w $data(ent) "tkFDialog_EntFocusOut $w"
1095
}
1096
 
1097
# tkFDialog_UpdateWhenIdle --
1098
#
1099
#       Creates an idle event handler which updates the dialog in idle
1100
#       time. This is important because loading the directory may take a long
1101
#       time and we don't want to load the same directory for multiple times
1102
#       due to multiple concurrent events.
1103
#
1104
proc tkFDialog_UpdateWhenIdle {w} {
1105
    upvar #0 [winfo name $w] data
1106
 
1107
    if {[info exists data(updateId)]} {
1108
        return
1109
    } else {
1110
        set data(updateId) [after idle tkFDialog_Update $w]
1111
    }
1112
}
1113
 
1114
# tkFDialog_Update --
1115
#
1116
#       Loads the files and directories into the IconList widget. Also
1117
#       sets up the directory option menu for quick access to parent
1118
#       directories.
1119
#
1120
proc tkFDialog_Update {w} {
1121
 
1122
    # This proc may be called within an idle handler. Make sure that the
1123
    # window has not been destroyed before this proc is called
1124
    if {![winfo exists $w] || [string compare [winfo class $w] TkFDialog]} {
1125
        return
1126
    }
1127
 
1128
    set dataName [winfo name $w]
1129
    upvar #0 $dataName data
1130
    global tk_library tkPriv
1131
    catch {unset data(updateId)}
1132
 
1133
    set TRANSPARENT_GIF_COLOR [$w cget -bg]
1134
    if {![info exists tkPriv(folderImage)]} {
1135
        set tkPriv(folderImage) [image create photo -data {
1136
R0lGODlhEAAMAKEAAAD//wAAAPD/gAAAACH5BAEAAAAALAAAAAAQAAwAAAIghINhyycvVFsB
1137
QtmS3rjaH1Hg141WaT5ouprt2HHcUgAAOw==}]
1138
        set tkPriv(fileImage)   [image create photo -data {
1139
R0lGODlhDAAMAKEAALLA3AAAAP//8wAAACH5BAEAAAAALAAAAAAMAAwAAAIgRI4Ha+IfWHsO
1140
rSASvJTGhnhcV3EJlo3kh53ltF5nAhQAOw==}]
1141
    }
1142
    set folder $tkPriv(folderImage)
1143
    set file   $tkPriv(fileImage)
1144
 
1145
    set appPWD [pwd]
1146
    if {[catch {
1147
        cd $data(selectPath)
1148
    }]} {
1149
        # We cannot change directory to $data(selectPath). $data(selectPath)
1150
        # should have been checked before tkFDialog_Update is called, so
1151
        # we normally won't come to here. Anyways, give an error and abort
1152
        # action.
1153
        tk_messageBox -type ok -parent $data(-parent) -message \
1154
            "Cannot change to the directory \"$data(selectPath)\".\nPermission denied."\
1155
            -icon warning
1156
        cd $appPWD
1157
        return
1158
    }
1159
 
1160
    # Turn on the busy cursor. BUG?? We haven't disabled X events, though,
1161
    # so the user may still click and cause havoc ...
1162
    #
1163
    set entCursor [$data(ent) cget -cursor]
1164
    set dlgCursor [$w         cget -cursor]
1165
    $data(ent) config -cursor watch
1166
    $w         config -cursor watch
1167
    update idletasks
1168
 
1169
    tkIconList_DeleteAll $data(icons)
1170
 
1171
    # Make the dir list
1172
    #
1173
    foreach f [lsort -dictionary [glob -nocomplain .* *]] {
1174
        if {![string compare $f .]} {
1175
            continue
1176
        }
1177
        if {![string compare $f ..]} {
1178
            continue
1179
        }
1180
        if {[file isdir ./$f]} {
1181
            if {![info exists hasDoneDir($f)]} {
1182
                tkIconList_Add $data(icons) $folder $f
1183
                set hasDoneDir($f) 1
1184
            }
1185
        }
1186
    }
1187
    # Make the file list
1188
    #
1189
    if {![string compare $data(filter) *]} {
1190
        set files [lsort -dictionary \
1191
            [glob -nocomplain .* *]]
1192
    } else {
1193
        set files [lsort -dictionary \
1194
            [eval glob -nocomplain $data(filter)]]
1195
    }
1196
 
1197
    set top 0
1198
    foreach f $files {
1199
        if {![file isdir ./$f]} {
1200
            if {![info exists hasDoneFile($f)]} {
1201
                tkIconList_Add $data(icons) $file $f
1202
                set hasDoneFile($f) 1
1203
            }
1204
        }
1205
    }
1206
 
1207
    tkIconList_Arrange $data(icons)
1208
 
1209
    # Update the Directory: option menu
1210
    #
1211
    set list ""
1212
    set dir ""
1213
    foreach subdir [file split $data(selectPath)] {
1214
        set dir [file join $dir $subdir]
1215
        lappend list $dir
1216
    }
1217
 
1218
    $data(dirMenu) delete 0 end
1219
    set var [format %s(selectPath) $dataName]
1220
    foreach path $list {
1221
        $data(dirMenu) add command -label $path -command [list set $var $path]
1222
    }
1223
 
1224
    # Restore the PWD to the application's PWD
1225
    #
1226
    cd $appPWD
1227
 
1228
    # turn off the busy cursor.
1229
    #
1230
    $data(ent) config -cursor $entCursor
1231
    $w         config -cursor $dlgCursor
1232
}
1233
 
1234
# tkFDialog_SetPathSilently --
1235
#
1236
#       Sets data(selectPath) without invoking the trace procedure
1237
#
1238
proc tkFDialog_SetPathSilently {w path} {
1239
    upvar #0 [winfo name $w] data
1240
 
1241
    trace vdelete  data(selectPath) w "tkFDialog_SetPath $w"
1242
    set data(selectPath) $path
1243
    trace variable data(selectPath) w "tkFDialog_SetPath $w"
1244
}
1245
 
1246
 
1247
# This proc gets called whenever data(selectPath) is set
1248
#
1249
proc tkFDialog_SetPath {w name1 name2 op} {
1250
    if {[winfo exists $w]} {
1251
        upvar #0 [winfo name $w] data
1252
        tkFDialog_UpdateWhenIdle $w
1253
    }
1254
}
1255
 
1256
# This proc gets called whenever data(filter) is set
1257
#
1258
proc tkFDialog_SetFilter {w type} {
1259
    upvar #0 [winfo name $w] data
1260
    upvar \#0 $data(icons) icons
1261
 
1262
    set data(filter) [lindex $type 1]
1263
    $data(typeMenuBtn) config -text [lindex $type 0] -indicatoron 1
1264
 
1265
    $icons(sbar) set 0.0 0.0
1266
 
1267
    tkFDialog_UpdateWhenIdle $w
1268
}
1269
 
1270
# tkFDialogResolveFile --
1271
#
1272
#       Interpret the user's text input in a file selection dialog.
1273
#       Performs:
1274
#
1275
#       (1) ~ substitution
1276
#       (2) resolve all instances of . and ..
1277
#       (3) check for non-existent files/directories
1278
#       (4) check for chdir permissions
1279
#
1280
# Arguments:
1281
#       context:  the current directory you are in
1282
#       text:     the text entered by the user
1283
#       defaultext: the default extension to add to files with no extension
1284
#
1285
# Return vaue:
1286
#       [list $flag $directory $file]
1287
#
1288
#        flag = OK      : valid input
1289
#             = PATTERN : valid directory/pattern
1290
#             = PATH    : the directory does not exist
1291
#             = FILE    : the directory exists by the file doesn't
1292
#                         exist
1293
#             = CHDIR   : Cannot change to the directory
1294
#             = ERROR   : Invalid entry
1295
#
1296
#        directory      : valid only if flag = OK or PATTERN or FILE
1297
#        file           : valid only if flag = OK or PATTERN
1298
#
1299
#       directory may not be the same as context, because text may contain
1300
#       a subdirectory name
1301
#
1302
proc tkFDialogResolveFile {context text defaultext} {
1303
 
1304
    set appPWD [pwd]
1305
 
1306
    set path [tkFDialog_JoinFile $context $text]
1307
 
1308
    if {[file ext $path] == ""} {
1309
        set path "$path$defaultext"
1310
    }
1311
 
1312
 
1313
    if {[catch {file exists $path}]} {
1314
        # This "if" block can be safely removed if the following code
1315
        # stop generating errors.
1316
        #
1317
        #       file exists ~nonsuchuser
1318
        #
1319
        return [list ERROR $path ""]
1320
    }
1321
 
1322
    if {[file exists $path]} {
1323
        if {[file isdirectory $path]} {
1324
            if {[catch {
1325
                cd $path
1326
            }]} {
1327
                return [list CHDIR $path ""]
1328
            }
1329
            set directory [pwd]
1330
            set file ""
1331
            set flag OK
1332
            cd $appPWD
1333
        } else {
1334
            if {[catch {
1335
                cd [file dirname $path]
1336
            }]} {
1337
                return [list CHDIR [file dirname $path] ""]
1338
            }
1339
            set directory [pwd]
1340
            set file [file tail $path]
1341
            set flag OK
1342
            cd $appPWD
1343
        }
1344
    } else {
1345
        set dirname [file dirname $path]
1346
        if {[file exists $dirname]} {
1347
            if {[catch {
1348
                cd $dirname
1349
            }]} {
1350
                return [list CHDIR $dirname ""]
1351
            }
1352
            set directory [pwd]
1353
            set file [file tail $path]
1354
            if {[regexp {[*]|[?]} $file]} {
1355
                set flag PATTERN
1356
            } else {
1357
                set flag FILE
1358
            }
1359
            cd $appPWD
1360
        } else {
1361
            set directory $dirname
1362
            set file [file tail $path]
1363
            set flag PATH
1364
        }
1365
    }
1366
 
1367
    return [list $flag $directory $file]
1368
}
1369
 
1370
 
1371
# Gets called when the entry box gets keyboard focus. We clear the selection
1372
# from the icon list . This way the user can be certain that the input in the 
1373
# entry box is the selection.
1374
#
1375
proc tkFDialog_EntFocusIn {w} {
1376
    upvar #0 [winfo name $w] data
1377
 
1378
    if {[string compare [$data(ent) get] ""]} {
1379
        $data(ent) selection from 0
1380
        $data(ent) selection to   end
1381
        $data(ent) icursor end
1382
    } else {
1383
        $data(ent) selection clear
1384
    }
1385
 
1386
    tkIconList_Unselect $data(icons)
1387
 
1388
    if {![string compare $data(type) open]} {
1389
        $data(okBtn) config -text "Open"
1390
    } else {
1391
        $data(okBtn) config -text "Save"
1392
    }
1393
}
1394
 
1395
proc tkFDialog_EntFocusOut {w} {
1396
    upvar #0 [winfo name $w] data
1397
 
1398
    $data(ent) selection clear
1399
}
1400
 
1401
 
1402
# Verification procedure
1403
proc tkFDialog_VerifyFileName { w fname } {
1404
    upvar #0 [winfo name $w] data
1405
 
1406
    set list [tkFDialogResolveFile $data(selectPath) $fname \
1407
                  $data(-defaultextension)]
1408
    set flag [lindex $list 0]
1409
    set path [lindex $list 1]
1410
    set file [lindex $list 2]
1411
 
1412
    case $flag {
1413
        OK {
1414
            if {![string compare $file ""]} {
1415
                tkFDialog_SetPathSilently $w [file dirname $path]
1416
                # CYGNUS LOCAL: handle choosedir
1417
                if {$data(-choosedir)} {
1418
                    if {$data(-multiple)} {
1419
                        lappend data(selectFile) [file tail $path]
1420
                    } else {
1421
                        set data(selectFile) [file tail $path]
1422
                    }
1423
                  tkFDialog_Done $w
1424
                } else {
1425
                    # user has entered an existing (sub)directory
1426
                    set data(selectPath) $path
1427
                    $data(ent) delete 0 end
1428
                }
1429
            } else {
1430
                tkFDialog_SetPathSilently $w $path
1431
                if {$data(-multiple)} {
1432
                    lappend data(selectFile) $file
1433
                } else {
1434
                    set data(selectFile) $file
1435
                }
1436
                tkFDialog_Done $w
1437
            }
1438
        }
1439
        PATTERN {
1440
            set data(selectPath) $path
1441
            set data(filter) $file
1442
        }
1443
        FILE {
1444
            if {![string compare $data(type) open]} {
1445
                tk_messageBox -icon warning -type ok -parent $data(-parent) \
1446
                    -message "File \"[file join $path $file]\" does not exist."
1447
                $data(ent) select from 0
1448
                $data(ent) select to   end
1449
                $data(ent) icursor end
1450
            } else {
1451
                tkFDialog_SetPathSilently $w $path
1452
                if {$data(-multiple)} {
1453
                    lappend data(selectFile) $file
1454
                } else {
1455
                    set data(selectFile) $file
1456
                }
1457
                tkFDialog_Done $w
1458
            }
1459
        }
1460
        PATH {
1461
            tk_messageBox -icon warning -type ok -parent $data(-parent) \
1462
                -message "Directory \"$path\" does not exist."
1463
            $data(ent) select from 0
1464
            $data(ent) select to   end
1465
            $data(ent) icursor end
1466
        }
1467
        CHDIR {
1468
            tk_messageBox -type ok -parent $data(-parent) -message \
1469
               "Cannot change to the directory \"$path\".\nPermission denied."\
1470
                -icon warning
1471
            $data(ent) select from 0
1472
            $data(ent) select to   end
1473
            $data(ent) icursor end
1474
        }
1475
        ERROR {
1476
            tk_messageBox -type ok -parent $data(-parent) -message \
1477
               "Invalid file name \"$path\"."\
1478
                -icon warning
1479
            $data(ent) select from 0
1480
            $data(ent) select to   end
1481
            $data(ent) icursor end
1482
        }
1483
    }
1484
}
1485
 
1486
# Gets called when user presses Return in the "File name" entry.
1487
#
1488
proc tkFDialog_ActivateEnt {w} {
1489
    upvar #0 [winfo name $w] data
1490
 
1491
    #set text [string trim [$data(ent) get]]
1492
    set text [$data(ent) get]
1493
    if {$data(-multiple)} {
1494
        set data(selectFile) ""
1495
        foreach fname $text {
1496
            tkFDialog_VerifyFileName $w $fname
1497
        }
1498
    } else {
1499
        tkFDialog_VerifyFileName $w $text
1500
    }
1501
}
1502
 
1503
# Gets called when user presses the Alt-s or Alt-o keys.
1504
#
1505
proc tkFDialog_InvokeBtn {w key} {
1506
    upvar #0 [winfo name $w] data
1507
 
1508
    if {![string compare [$data(okBtn) cget -text] $key]} {
1509
        tkButtonInvoke $data(okBtn)
1510
    }
1511
}
1512
 
1513
# Gets called when user presses the "parent directory" button
1514
#
1515
proc tkFDialog_UpDirCmd {w} {
1516
    upvar #0 [winfo name $w] data
1517
 
1518
    if {[string compare $data(selectPath) "/"]} {
1519
        set data(selectPath) [file dirname $data(selectPath)]
1520
    }
1521
}
1522
 
1523
# Join a file name to a path name. The "file join" command will break
1524
# if the filename begins with ~
1525
#
1526
proc tkFDialog_JoinFile {path file} {
1527
    if {[string match {~*} $file] && [file exists $path/$file]} {
1528
        return [file join $path ./$file]
1529
    } else {
1530
        return [file join $path $file]
1531
    }
1532
}
1533
 
1534
 
1535
 
1536
# Gets called when user presses the "OK" button
1537
#
1538
proc tkFDialog_OkCmd {w} {
1539
    upvar #0 [winfo name $w] data
1540
 
1541
    set text [tkIconList_Get $data(icons)]
1542
    if {[string compare $text ""]} {
1543
        if {!$data(-multiple)} {
1544
            set file [tkFDialog_JoinFile $data(selectPath) $text]
1545
            # CYGNUS LOCAL: handle choosedir
1546
            if {!$data(-choosedir) && [file isdirectory $file]} {
1547
                tkFDialog_ListInvoke $w $text
1548
                return
1549
            }
1550
        }
1551
    }
1552
 
1553
    tkFDialog_ActivateEnt $w
1554
}
1555
 
1556
# Gets called when user presses the "Cancel" button
1557
#
1558
proc tkFDialog_CancelCmd {w} {
1559
    upvar #0 [winfo name $w] data
1560
    global tkPriv
1561
 
1562
    set tkPriv(selectFilePath) ""
1563
}
1564
 
1565
# Gets called when user browses the IconList widget (dragging mouse, arrow
1566
# keys, etc)
1567
#
1568
proc tkFDialog_ListBrowse {w text} {
1569
    upvar #0 [winfo name $w] data
1570
 
1571
    if {$text == ""} {
1572
        return
1573
    }
1574
 
1575
    set file [tkFDialog_JoinFile $data(selectPath) $text]
1576
    # CYGNUS LOCAL: handle choosedir
1577
    if {$data(-choosedir) || ![file isdirectory $file]} {
1578
        $data(ent) delete 0 end
1579
        $data(ent) insert 0 $text
1580
 
1581
        if {![string compare $data(type) open]} {
1582
            $data(okBtn) config -text "Open"
1583
        } else {
1584
            $data(okBtn) config -text "Save"
1585
        }
1586
    } else {
1587
        $data(okBtn) config -text "Open"
1588
    }
1589
}
1590
 
1591
# Gets called when user invokes the IconList widget (double-click, 
1592
# Return key, etc)
1593
#
1594
proc tkFDialog_ListInvoke {w text} {
1595
    upvar #0 [winfo name $w] data
1596
 
1597
    if {$text == ""} {
1598
        return
1599
    }
1600
 
1601
    if {$data(-multiple)} {
1602
        set file [tkFDialog_JoinFile $data(selectPath) [lindex $text 0]]
1603
    } else {
1604
        set file [tkFDialog_JoinFile $data(selectPath) $text]
1605
    }
1606
 
1607
    if {[file isdirectory $file]} {
1608
        set appPWD [pwd]
1609
        if {[catch {cd $file}]} {
1610
            tk_messageBox -type ok -parent $data(-parent) -message \
1611
               "Cannot change to the directory \"$file\".\nPermission denied."\
1612
                -icon warning
1613
        } else {
1614
            cd $appPWD
1615
            set data(selectPath) $file
1616
        }
1617
    } else {
1618
        if {$data(-multiple)} {
1619
            set data(selectFile) [list $file]
1620
        } else {
1621
            set data(selectFile) $file
1622
        }
1623
        tkFDialog_Done $w
1624
    }
1625
}
1626
 
1627
# tkFDialog_Done --
1628
#
1629
#       Gets called when user has input a valid filename.  Pops up a
1630
#       dialog box to confirm selection when necessary. Sets the
1631
#       tkPriv(selectFilePath) variable, which will break the "tkwait"
1632
#       loop in tkFDialog and return the selected filename to the
1633
#       script that calls tk_getOpenFile or tk_getSaveFile
1634
#
1635
proc tkFDialog_Done {w {selectFilePath ""}} {
1636
    upvar #0 [winfo name $w] data
1637
    global tkPriv
1638
 
1639
    if {![string compare $selectFilePath ""]} {
1640
        if {$data(-multiple)} {
1641
            set selectFilePath {}
1642
            foreach f $data(selectFile) {
1643
                lappend selectFilePath [file join $data(selectPath) $f]
1644
            }
1645
        } else {
1646
            set selectFilePath [tkFDialog_JoinFile $data(selectPath) \
1647
                    $data(selectFile)]
1648
        }
1649
        set tkPriv(selectFile)     $data(selectFile)
1650
        set tkPriv(selectPath)     $data(selectPath)
1651
 
1652
        if {[file exists $selectFilePath] &&
1653
            ![string compare $data(type) save]} {
1654
 
1655
                set reply [tk_messageBox -icon warning -type yesno\
1656
                        -parent $data(-parent) -message "File\
1657
                        \"$selectFilePath\" already exists.\nDo\
1658
                        you want to overwrite it?"]
1659
                if {![string compare $reply "no"]} {
1660
                    return
1661
                }
1662
        }
1663
    }
1664
    set tkPriv(selectFilePath) $selectFilePath
1665
}
1666
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.