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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tk/] [library/] [tkfbox.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) [list $data(selected)]
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
    if {![info exists tkPriv(folderImage)]} {
1134
        set tkPriv(folderImage) [image create photo -data {
1135
R0lGODlhEAAMAKEAAAD//wAAAPD/gAAAACH5BAEAAAAALAAAAAAQAAwAAAIghINhyycvVFsB
1136
QtmS3rjaH1Hg141WaT5ouprt2HHcUgAAOw==}]
1137
        set tkPriv(fileImage)   [image create photo -data {
1138
R0lGODlhDAAMAKEAALLA3AAAAP//8wAAACH5BAEAAAAALAAAAAAMAAwAAAIgRI4Ha+IfWHsO
1139
rSASvJTGhnhcV3EJlo3kh53ltF5nAhQAOw==}]
1140
    }
1141
    set folder $tkPriv(folderImage)
1142
    set file   $tkPriv(fileImage)
1143
 
1144
    set appPWD [pwd]
1145
    if {[catch {
1146
        cd $data(selectPath)
1147
    }]} {
1148
        # We cannot change directory to $data(selectPath). $data(selectPath)
1149
        # should have been checked before tkFDialog_Update is called, so
1150
        # we normally won't come to here. Anyways, give an error and abort
1151
        # action.
1152
        tk_messageBox -type ok -parent $data(-parent) -message \
1153
            "Cannot change to the directory \"$data(selectPath)\".\nPermission denied."\
1154
            -icon warning
1155
        cd $appPWD
1156
        return
1157
    }
1158
 
1159
    # Turn on the busy cursor. BUG?? We haven't disabled X events, though,
1160
    # so the user may still click and cause havoc ...
1161
    #
1162
    set entCursor [$data(ent) cget -cursor]
1163
    set dlgCursor [$w         cget -cursor]
1164
    $data(ent) config -cursor watch
1165
    $w         config -cursor watch
1166
    update idletasks
1167
 
1168
    tkIconList_DeleteAll $data(icons)
1169
 
1170
    # Make the dir list
1171
    #
1172
    foreach f [lsort -dictionary [glob -nocomplain .* *]] {
1173
        if {![string compare $f .]} {
1174
            continue
1175
        }
1176
        if {![string compare $f ..]} {
1177
            continue
1178
        }
1179
        if {[file isdir ./$f]} {
1180
            if {![info exists hasDoneDir($f)]} {
1181
                tkIconList_Add $data(icons) $folder $f
1182
                set hasDoneDir($f) 1
1183
            }
1184
        }
1185
    }
1186
    # Make the file list
1187
    #
1188
    if {![string compare $data(filter) *]} {
1189
        set files [lsort -dictionary \
1190
            [glob -nocomplain .* *]]
1191
    } else {
1192
        set files [lsort -dictionary \
1193
            [eval glob -nocomplain $data(filter)]]
1194
    }
1195
 
1196
    set top 0
1197
    foreach f $files {
1198
        if {![file isdir ./$f]} {
1199
            if {![info exists hasDoneFile($f)]} {
1200
                tkIconList_Add $data(icons) $file $f
1201
                set hasDoneFile($f) 1
1202
            }
1203
        }
1204
    }
1205
 
1206
    tkIconList_Arrange $data(icons)
1207
 
1208
    # Update the Directory: option menu
1209
    #
1210
    set list ""
1211
    set dir ""
1212
    foreach subdir [file split $data(selectPath)] {
1213
        set dir [file join $dir $subdir]
1214
        lappend list $dir
1215
    }
1216
 
1217
    $data(dirMenu) delete 0 end
1218
    set var [format %s(selectPath) $dataName]
1219
    foreach path $list {
1220
        $data(dirMenu) add command -label $path -command [list set $var $path]
1221
    }
1222
 
1223
    # Restore the PWD to the application's PWD
1224
    #
1225
    cd $appPWD
1226
 
1227
    # turn off the busy cursor.
1228
    #
1229
    $data(ent) config -cursor $entCursor
1230
    $w         config -cursor $dlgCursor
1231
}
1232
 
1233
# tkFDialog_SetPathSilently --
1234
#
1235
#       Sets data(selectPath) without invoking the trace procedure
1236
#
1237
proc tkFDialog_SetPathSilently {w path} {
1238
    upvar #0 [winfo name $w] data
1239
 
1240
    trace vdelete  data(selectPath) w "tkFDialog_SetPath $w"
1241
    set data(selectPath) $path
1242
    trace variable data(selectPath) w "tkFDialog_SetPath $w"
1243
}
1244
 
1245
 
1246
# This proc gets called whenever data(selectPath) is set
1247
#
1248
proc tkFDialog_SetPath {w name1 name2 op} {
1249
    if {[winfo exists $w]} {
1250
        upvar #0 [winfo name $w] data
1251
        tkFDialog_UpdateWhenIdle $w
1252
    }
1253
}
1254
 
1255
# This proc gets called whenever data(filter) is set
1256
#
1257
proc tkFDialog_SetFilter {w type} {
1258
    upvar #0 [winfo name $w] data
1259
    upvar \#0 $data(icons) icons
1260
 
1261
    set data(filter) [lindex $type 1]
1262
    $data(typeMenuBtn) config -text [lindex $type 0] -indicatoron 1
1263
 
1264
    $icons(sbar) set 0.0 0.0
1265
 
1266
    tkFDialog_UpdateWhenIdle $w
1267
}
1268
 
1269
# tkFDialogResolveFile --
1270
#
1271
#       Interpret the user's text input in a file selection dialog.
1272
#       Performs:
1273
#
1274
#       (1) ~ substitution
1275
#       (2) resolve all instances of . and ..
1276
#       (3) check for non-existent files/directories
1277
#       (4) check for chdir permissions
1278
#
1279
# Arguments:
1280
#       context:  the current directory you are in
1281
#       text:     the text entered by the user
1282
#       defaultext: the default extension to add to files with no extension
1283
#
1284
# Return vaue:
1285
#       [list $flag $directory $file]
1286
#
1287
#        flag = OK      : valid input
1288
#             = PATTERN : valid directory/pattern
1289
#             = PATH    : the directory does not exist
1290
#             = FILE    : the directory exists by the file doesn't
1291
#                         exist
1292
#             = CHDIR   : Cannot change to the directory
1293
#             = ERROR   : Invalid entry
1294
#
1295
#        directory      : valid only if flag = OK or PATTERN or FILE
1296
#        file           : valid only if flag = OK or PATTERN
1297
#
1298
#       directory may not be the same as context, because text may contain
1299
#       a subdirectory name
1300
#
1301
proc tkFDialogResolveFile {context text defaultext} {
1302
 
1303
    set appPWD [pwd]
1304
 
1305
    set path [tkFDialog_JoinFile $context $text]
1306
 
1307
    if {[file ext $path] == ""} {
1308
        set path "$path$defaultext"
1309
    }
1310
 
1311
 
1312
    if {[catch {file exists $path}]} {
1313
        # This "if" block can be safely removed if the following code
1314
        # stop generating errors.
1315
        #
1316
        #       file exists ~nonsuchuser
1317
        #
1318
        return [list ERROR $path ""]
1319
    }
1320
 
1321
    if {[file exists $path]} {
1322
        if {[file isdirectory $path]} {
1323
            if {[catch {
1324
                cd $path
1325
            }]} {
1326
                return [list CHDIR $path ""]
1327
            }
1328
            set directory [pwd]
1329
            set file ""
1330
            set flag OK
1331
            cd $appPWD
1332
        } else {
1333
            if {[catch {
1334
                cd [file dirname $path]
1335
            }]} {
1336
                return [list CHDIR [file dirname $path] ""]
1337
            }
1338
            set directory [pwd]
1339
            set file [file tail $path]
1340
            set flag OK
1341
            cd $appPWD
1342
        }
1343
    } else {
1344
        set dirname [file dirname $path]
1345
        if {[file exists $dirname]} {
1346
            if {[catch {
1347
                cd $dirname
1348
            }]} {
1349
                return [list CHDIR $dirname ""]
1350
            }
1351
            set directory [pwd]
1352
            set file [file tail $path]
1353
            if {[regexp {[*]|[?]} $file]} {
1354
                set flag PATTERN
1355
            } else {
1356
                set flag FILE
1357
            }
1358
            cd $appPWD
1359
        } else {
1360
            set directory $dirname
1361
            set file [file tail $path]
1362
            set flag PATH
1363
        }
1364
    }
1365
 
1366
    return [list $flag $directory $file]
1367
}
1368
 
1369
 
1370
# Gets called when the entry box gets keyboard focus. We clear the selection
1371
# from the icon list . This way the user can be certain that the input in the 
1372
# entry box is the selection.
1373
#
1374
proc tkFDialog_EntFocusIn {w} {
1375
    upvar #0 [winfo name $w] data
1376
 
1377
    if {[string compare [$data(ent) get] ""]} {
1378
        $data(ent) selection from 0
1379
        $data(ent) selection to   end
1380
        $data(ent) icursor end
1381
    } else {
1382
        $data(ent) selection clear
1383
    }
1384
 
1385
    tkIconList_Unselect $data(icons)
1386
 
1387
    if {![string compare $data(type) open]} {
1388
        $data(okBtn) config -text "Open"
1389
    } else {
1390
        $data(okBtn) config -text "Save"
1391
    }
1392
}
1393
 
1394
proc tkFDialog_EntFocusOut {w} {
1395
    upvar #0 [winfo name $w] data
1396
 
1397
    $data(ent) selection clear
1398
}
1399
 
1400
 
1401
# Verification procedure
1402
proc tkFDialog_VerifyFileName { w fname } {
1403
    upvar #0 [winfo name $w] data
1404
 
1405
    set list [tkFDialogResolveFile $data(selectPath) $fname \
1406
                  $data(-defaultextension)]
1407
    set flag [lindex $list 0]
1408
    set path [lindex $list 1]
1409
    set file [lindex $list 2]
1410
 
1411
    case $flag {
1412
        OK {
1413
            if {![string compare $file ""]} {
1414
                tkFDialog_SetPathSilently $w [file dirname $path]
1415
                # CYGNUS LOCAL: handle choosedir
1416
                if {$data(-choosedir)} {
1417
                    if {$data(-multiple)} {
1418
                        lappend data(selectFile) [file tail $path]
1419
                    } else {
1420
                        set data(selectFile) [file tail $path]
1421
                    }
1422
                  tkFDialog_Done $w
1423
                } else {
1424
                    # user has entered an existing (sub)directory
1425
                    set data(selectPath) $path
1426
                    $data(ent) delete 0 end
1427
                }
1428
            } else {
1429
                tkFDialog_SetPathSilently $w $path
1430
                if {$data(-multiple)} {
1431
                    lappend data(selectFile) $file
1432
                } else {
1433
                    set data(selectFile) $file
1434
                }
1435
                tkFDialog_Done $w
1436
            }
1437
        }
1438
        PATTERN {
1439
            set data(selectPath) $path
1440
            set data(filter) $file
1441
        }
1442
        FILE {
1443
            if {![string compare $data(type) open]} {
1444
                tk_messageBox -icon warning -type ok -parent $data(-parent) \
1445
                    -message "File \"[file join $path $file]\" does not exist."
1446
                $data(ent) select from 0
1447
                $data(ent) select to   end
1448
                $data(ent) icursor end
1449
            } else {
1450
                tkFDialog_SetPathSilently $w $path
1451
                if {$data(-multiple)} {
1452
                    lappend data(selectFile) $file
1453
                } else {
1454
                    set data(selectFile) $file
1455
                }
1456
                tkFDialog_Done $w
1457
            }
1458
        }
1459
        PATH {
1460
            tk_messageBox -icon warning -type ok -parent $data(-parent) \
1461
                -message "Directory \"$path\" does not exist."
1462
            $data(ent) select from 0
1463
            $data(ent) select to   end
1464
            $data(ent) icursor end
1465
        }
1466
        CHDIR {
1467
            tk_messageBox -type ok -parent $data(-parent) -message \
1468
               "Cannot change to the directory \"$path\".\nPermission denied."\
1469
                -icon warning
1470
            $data(ent) select from 0
1471
            $data(ent) select to   end
1472
            $data(ent) icursor end
1473
        }
1474
        ERROR {
1475
            tk_messageBox -type ok -parent $data(-parent) -message \
1476
               "Invalid file name \"$path\"."\
1477
                -icon warning
1478
            $data(ent) select from 0
1479
            $data(ent) select to   end
1480
            $data(ent) icursor end
1481
        }
1482
    }
1483
}
1484
 
1485
# Gets called when user presses Return in the "File name" entry.
1486
#
1487
proc tkFDialog_ActivateEnt {w} {
1488
    upvar #0 [winfo name $w] data
1489
 
1490
    #set text [string trim [$data(ent) get]]
1491
    set text [$data(ent) get]
1492
    if {$data(-multiple)} {
1493
        set data(selectFile) ""
1494
        foreach fname $text {
1495
            tkFDialog_VerifyFileName $w $fname
1496
        }
1497
    } else {
1498
        tkFDialog_VerifyFileName $w $text
1499
    }
1500
}
1501
 
1502
# Gets called when user presses the Alt-s or Alt-o keys.
1503
#
1504
proc tkFDialog_InvokeBtn {w key} {
1505
    upvar #0 [winfo name $w] data
1506
 
1507
    if {![string compare [$data(okBtn) cget -text] $key]} {
1508
        tkButtonInvoke $data(okBtn)
1509
    }
1510
}
1511
 
1512
# Gets called when user presses the "parent directory" button
1513
#
1514
proc tkFDialog_UpDirCmd {w} {
1515
    upvar #0 [winfo name $w] data
1516
 
1517
    if {[string compare $data(selectPath) "/"]} {
1518
        set data(selectPath) [file dirname $data(selectPath)]
1519
    }
1520
}
1521
 
1522
# Join a file name to a path name. The "file join" command will break
1523
# if the filename begins with ~
1524
#
1525
proc tkFDialog_JoinFile {path file} {
1526
    if {[string match {~*} $file] && [file exists $path/$file]} {
1527
        return [file join $path ./$file]
1528
    } else {
1529
        return [file join $path $file]
1530
    }
1531
}
1532
 
1533
 
1534
 
1535
# Gets called when user presses the "OK" button
1536
#
1537
proc tkFDialog_OkCmd {w} {
1538
    upvar #0 [winfo name $w] data
1539
 
1540
    set text [tkIconList_Get $data(icons)]
1541
    if {[string compare $text ""]} {
1542
        if {!$data(-multiple)} {
1543
            set file [tkFDialog_JoinFile $data(selectPath) $text]
1544
            # CYGNUS LOCAL: handle choosedir
1545
            if {!$data(-choosedir) && [file isdirectory $file]} {
1546
                tkFDialog_ListInvoke $w $text
1547
                return
1548
            }
1549
        }
1550
    }
1551
 
1552
    tkFDialog_ActivateEnt $w
1553
}
1554
 
1555
# Gets called when user presses the "Cancel" button
1556
#
1557
proc tkFDialog_CancelCmd {w} {
1558
    upvar #0 [winfo name $w] data
1559
    global tkPriv
1560
 
1561
    set tkPriv(selectFilePath) ""
1562
}
1563
 
1564
# Gets called when user browses the IconList widget (dragging mouse, arrow
1565
# keys, etc)
1566
#
1567
proc tkFDialog_ListBrowse {w text} {
1568
    upvar #0 [winfo name $w] data
1569
 
1570
    if {$text == ""} {
1571
        return
1572
    }
1573
 
1574
    set file [tkFDialog_JoinFile $data(selectPath) $text]
1575
    # CYGNUS LOCAL: handle choosedir
1576
    if {$data(-choosedir) || ![file isdirectory $file]} {
1577
        $data(ent) delete 0 end
1578
        $data(ent) insert 0 $text
1579
 
1580
        if {![string compare $data(type) open]} {
1581
            $data(okBtn) config -text "Open"
1582
        } else {
1583
            $data(okBtn) config -text "Save"
1584
        }
1585
    } else {
1586
        $data(okBtn) config -text "Open"
1587
    }
1588
}
1589
 
1590
# Gets called when user invokes the IconList widget (double-click, 
1591
# Return key, etc)
1592
#
1593
proc tkFDialog_ListInvoke {w text} {
1594
    upvar #0 [winfo name $w] data
1595
 
1596
    if {$text == ""} {
1597
        return
1598
    }
1599
 
1600
    if {$data(-multiple)} {
1601
        set file [tkFDialog_JoinFile $data(selectPath) [lindex $text 0]]
1602
    } else {
1603
        set file [tkFDialog_JoinFile $data(selectPath) $text]
1604
    }
1605
 
1606
    if {[file isdirectory $file]} {
1607
        set appPWD [pwd]
1608
        if {[catch {cd $file}]} {
1609
            tk_messageBox -type ok -parent $data(-parent) -message \
1610
               "Cannot change to the directory \"$file\".\nPermission denied."\
1611
                -icon warning
1612
        } else {
1613
            cd $appPWD
1614
            set data(selectPath) $file
1615
        }
1616
    } else {
1617
        if {$data(-multiple)} {
1618
            set data(selectFile) [list $file]
1619
        } else {
1620
            set data(selectFile) $file
1621
        }
1622
        tkFDialog_Done $w
1623
    }
1624
}
1625
 
1626
# tkFDialog_Done --
1627
#
1628
#       Gets called when user has input a valid filename.  Pops up a
1629
#       dialog box to confirm selection when necessary. Sets the
1630
#       tkPriv(selectFilePath) variable, which will break the "tkwait"
1631
#       loop in tkFDialog and return the selected filename to the
1632
#       script that calls tk_getOpenFile or tk_getSaveFile
1633
#
1634
proc tkFDialog_Done {w {selectFilePath ""}} {
1635
    upvar #0 [winfo name $w] data
1636
    global tkPriv
1637
 
1638
    if {![string compare $selectFilePath ""]} {
1639
        if {$data(-multiple)} {
1640
            set selectFilePath {}
1641
            foreach f $data(selectFile) {
1642
                lappend selectFilePath [file join $data(selectPath) $f]
1643
            }
1644
        } else {
1645
            set selectFilePath [tkFDialog_JoinFile $data(selectPath) \
1646
                    $data(selectFile)]
1647
        }
1648
        set tkPriv(selectFile)     $data(selectFile)
1649
        set tkPriv(selectPath)     $data(selectPath)
1650
 
1651
        if {[file exists $selectFilePath] &&
1652
            ![string compare $data(type) save]} {
1653
 
1654
                set reply [tk_messageBox -icon warning -type yesno\
1655
                        -parent $data(-parent) -message "File\
1656
                        \"$selectFilePath\" already exists.\nDo\
1657
                        you want to overwrite it?"]
1658
                if {![string compare $reply "no"]} {
1659
                    return
1660
                }
1661
        }
1662
    }
1663
    set tkPriv(selectFilePath) $selectFilePath
1664
}
1665
 

powered by: WebSVN 2.1.0

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