FileBrowser.st
changeset 1834 1c0681c82eae
parent 1828 afb2a1533571
child 1835 05dc421fee95
--- a/FileBrowser.st	Fri Aug 14 18:04:01 1998 +0200
+++ b/FileBrowser.st	Fri Aug 14 18:18:08 1998 +0200
@@ -12,12 +12,12 @@
 
 StandardSystemView subclass:#FileBrowser
 	instanceVariableNames:'labelView filterField fileListView subView currentDirectory
-		fileList checkBlock checkDelta timeOfLastCheck showLongList
-		showDotFiles myName killButton pauseToggle compressTabs
-		lockUpdate previousDirectory currentFileName timeOfFileRead
-		tabSpec commandView commandIndex fileEncoding tabRulerView
-		scrollView icons listUpdateProcess currentFileInFileName
-		lastFileDiffDirectory'
+		fileList checkBlock checkDelta timeOfLastCheck myName killButton
+		pauseToggle compressTabs lockUpdate previousDirectory
+		currentFileName timeOfFileRead tabSpec commandView commandIndex
+		fileEncoding tabRulerView scrollView icons listUpdateProcess
+		currentFileInFileName lastFileDiffDirectory sortByWhat
+		sortCaseless showingDetails showingHiddenFiles'
 	classVariableNames:'DirectoryHistory DirectoryHistoryWhere HistorySize DefaultIcon
 		CommandHistory CommandHistorySize Icons DefaultCommandPerSuffix'
 	poolDictionaries:''
@@ -225,6 +225,639 @@
     "Modified: 15.8.1997 / 15:27:19 / cg"
 ! !
 
+!FileBrowser class methodsFor:'menu specs'!
+
+baseDirectoryMenuSpec
+    "This resource specification was automatically generated
+     by the MenuEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the MenuEditor may not be able to read the specification."
+
+    "
+     MenuEditor new openOnClass:FileBrowser andSelector:#directoryMenuSpec
+     (Menu new fromLiteralArrayEncoding:(FileBrowser directoryMenuSpec)) startUp
+    "
+
+    <resource: #menu>
+
+    ^
+     
+       #(#Menu
+          
+           #(
+             #(#MenuItem
+                #label: 'Up'
+                #translateLabel: true
+                #value: #changeToParentDirectory
+                #enabled: #currentDirectoryIsNotTop
+            )
+             #(#MenuItem
+                #label: 'Back'
+                #translateLabel: true
+                #value: #changeToPreviousDirectory
+            )
+             #(#MenuItem
+                #label: 'Home'
+                #translateLabel: true
+                #value: #changeToHomeDirectory
+            )
+             #(#MenuItem
+                #label: 'Default'
+                #translateLabel: true
+                #value: #changeToDefaultDirectory
+            )
+             #(#MenuItem
+                #label: 'Goto...'
+                #translateLabel: true
+                #value: #changeCurrentDirectory
+            )
+             #(#MenuItem
+                #label: '-'
+            )
+          ) nil
+          nil
+      )
+
+    "Created: / 4.8.1998 / 17:21:16 / cg"
+    "Modified: / 14.8.1998 / 12:08:14 / cg"
+!
+
+directoryMenuSpec
+    "This resource specification was automatically generated
+     by the MenuEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the MenuEditor may not be able to read the specification."
+
+    "
+     MenuEditor new openOnClass:FileBrowser andSelector:#directoryMenuSpec
+     (Menu new fromLiteralArrayEncoding:(FileBrowser directoryMenuSpec)) startUp
+    "
+
+    <resource: #programMenu>
+
+    |base|
+
+    base := self baseDirectoryMenuSpec.
+    base := base decodeAsLiteralArray.
+
+    "/ add the history items ...
+
+    DirectoryHistory do:[:dirName |
+        base addItem:((MenuItem label:dirName value:#changeDirectoryTo:)
+                        argument:dirName;
+                        yourself).
+    ].
+
+    ^ base
+
+    "Modified: / 4.8.1998 / 17:35:47 / cg"
+!
+
+menuPopUp
+    "This resource specification was automatically generated
+     by the MenuEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the MenuEditor may not be able to read the specification."
+
+    "
+     MenuEditor new openOnClass:FileBrowser andSelector:#menuPopUp
+     (Menu new fromLiteralArrayEncoding:(FileBrowser menuPopUp)) startUp
+    "
+
+    <resource: #menu>
+
+    ^
+     
+       #(#Menu
+          
+           #(
+             #(#MenuItem
+                #label: 'Spawn'
+                #translateLabel: true
+                #value: #fileSpawn
+            )
+             #(#MenuItem
+                #label: '-'
+            )
+             #(#MenuItem
+                #label: 'Get Contents'
+                #translateLabel: true
+                #enabled: #hasSelection
+            )
+             #(#MenuItem
+                #label: 'Insert Contents'
+                #translateLabel: true
+                #enabled: #hasSelection
+                #value: #fileInsert
+            )
+             #(#MenuItem
+                #label: 'FileIn'
+                #translateLabel: true
+                #value: #fileFileIn
+                #enabled: #hasSelection
+            )
+             #(#MenuItem
+                #label: '-'
+            )
+             #(#MenuItem
+                #label: 'Unix Command...'
+                #translateLabel: true
+                #isVisible: #systemIsUnix
+                #value: #menuOSCommand
+            )
+             #(#MenuItem
+                #label: 'DOS Command...'
+                #translateLabel: true
+                #isVisible: #systemIsDOS
+                #value: #menuOSCommand
+            )
+             #(#MenuItem
+                #label: 'VMS Command...'
+                #translateLabel: true
+                #isVisible: #systemIsVMS
+                #value: #menuOSCommand
+            )
+             #(#MenuItem
+                #label: 'ST/X Tools'
+                #translateLabel: true
+                #submenu: 
+                 #(#Menu
+                    
+                     #(
+                       #(#MenuItem
+                          #label: 'Changes Browser'
+                          #translateLabel: true
+                          #value: #openChangesBrowser
+                          #enabled: #hasSelection
+                      )
+                       #(#MenuItem
+                          #label: 'Editor'
+                          #translateLabel: true
+                          #enabled: #hasSelection
+                          #value: #openEditor
+                      )
+                       #(#MenuItem
+                          #label: 'HTML Reader'
+                          #translateLabel: true
+                          #enabled: #hasSelection
+                          #value: #openHTMLReader
+                      )
+                       #(#MenuItem
+                          #label: 'Image Inspect'
+                          #translateLabel: true
+                          #enabled: #hasSelection
+                          #value: #openImageInspector
+                      )
+                       #(#MenuItem
+                          #label: 'Image Editor'
+                          #translateLabel: true
+                          #enabled: #hasSelection
+                          #value: #openImageEditor
+                      )
+                       #(#MenuItem
+                          #label: 'Show File Differences'
+                          #translateLabel: true
+                          #value: #openDiffView
+                      )
+                       #(#MenuItem
+                          #label: 'Terminal'
+                          #translateLabel: true
+                          #value: #openTerminal
+                      )
+                    ) nil
+                    nil
+                )
+            )
+             #(#MenuItem
+                #label: '-'
+            )
+             #(#MenuItem
+                #label: 'Remove...'
+                #translateLabel: true
+                #enabled: #hasSelection
+                #value: #fileRemove
+            )
+             #(#MenuItem
+                #label: 'Rename...'
+                #translateLabel: true
+                #enabled: #hasSelection
+                #value: #fileRename
+            )
+             #(#MenuItem
+                #label: '-'
+            )
+             #(#MenuItem
+                #label: 'New Directory...'
+                #translateLabel: true
+            )
+             #(#MenuItem
+                #label: 'New File...'
+                #translateLabel: true
+            )
+             #(#MenuItem
+                #label: '-'
+            )
+             #(#MenuItem
+                #label: 'Update'
+                #translateLabel: true
+                #value: #updateCurrentDirectory
+            )
+          ) nil
+          nil
+      )
+
+    "Modified: / 14.8.1998 / 18:02:18 / cg"
+!
+
+menuSpec
+    "This resource specification was automatically generated
+     by the MenuEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the MenuEditor may not be able to read the specification."
+
+    "
+     MenuEditor new openOnClass:FileBrowser andSelector:#menuSpec
+     (Menu new fromLiteralArrayEncoding:(FileBrowser menuSpec)) startUp
+    "
+
+    <resource: #menu>
+
+    ^
+     
+       #(#Menu
+          
+           #(
+             #(#MenuItem
+                #label: 'About'
+                #translateLabel: true
+                #labelImage: #(#ResourceRetriever #ToolApplicationModel #menuIcon)
+                #submenu: 
+                 #(#Menu
+                    
+                     #(
+                       #(#MenuItem
+                          #label: 'About Smalltalk/X...'
+                          #translateLabel: true
+                          #value: #showAboutSTX
+                      )
+                       #(#MenuItem
+                          #label: '-'
+                      )
+                       #(#MenuItem
+                          #label: 'About FileBrowser...'
+                          #translateLabel: true
+                          #value: #openAboutThisApplication
+                      )
+                    ) nil
+                    nil
+                )
+            )
+             #(#MenuItem
+                #label: 'File'
+                #translateLabel: true
+                #submenu: 
+                 #(#Menu
+                    
+                     #(
+                       #(#MenuItem
+                          #label: 'Open'
+                          #translateLabel: true
+                          #value: #menuOpen
+                          #enabled: #hasSelection
+                      )
+                       #(#MenuItem
+                          #label: 'FileIn'
+                          #translateLabel: true
+                          #value: #fileFileIn
+                          #enabled: #hasSelection
+                      )
+                       #(#MenuItem
+                          #label: '-'
+                      )
+                       #(#MenuItem
+                          #label: 'New'
+                          #translateLabel: true
+                          #submenu: 
+                           #(#Menu
+                              
+                               #(
+                                 #(#MenuItem
+                                    #label: 'Directory...'
+                                    #translateLabel: true
+                                    #value: #newDirectory
+                                )
+                                 #(#MenuItem
+                                    #label: 'File...'
+                                    #translateLabel: true
+                                    #value: #newFile
+                                )
+                                 #(#MenuItem
+                                    #label: 'Hard Link...'
+                                    #translateLabel: true
+                                    #isVisible: #systemIsUnix
+                                    #value: #newHardLink
+                                )
+                                 #(#MenuItem
+                                    #label: 'Symbolic Link...'
+                                    #translateLabel: true
+                                    #isVisible: #systemIsUnix
+                                    #value: #newSoftLink
+                                )
+                              ) nil
+                              nil
+                          )
+                      )
+                       #(#MenuItem
+                          #label: 'Remove'
+                          #translateLabel: true
+                          #value: #fileRemove
+                          #enabled: #hasSelection
+                      )
+                       #(#MenuItem
+                          #label: 'Rename'
+                          #translateLabel: true
+                          #value: #fileRename
+                          #enabled: #hasSelection
+                      )
+                       #(#MenuItem
+                          #label: 'Properties...'
+                          #translateLabel: true
+                          #value: #fileGetLongInfo
+                          #enabled: #hasSelection
+                      )
+                       #(#MenuItem
+                          #label: '-'
+                      )
+                       #(#MenuItem
+                          #label: 'Spawn'
+                          #translateLabel: true
+                          #value: #fileSpawn
+                      )
+                       #(#MenuItem
+                          #label: '-'
+                      )
+                       #(#MenuItem
+                          #label: 'Exit'
+                          #translateLabel: true
+                          #value: #menuExit
+                      )
+                    ) nil
+                    nil
+                )
+            )
+             #(#MenuItem
+                #label: 'Directory'
+                #translateLabel: true
+                #submenuChannel: #directoryMenuSpec
+            )
+             #(#MenuItem
+                #label: 'Edit'
+                #translateLabel: true
+                #submenu: 
+                 #(#Menu
+                    
+                     #(
+                       #(#MenuItem
+                          #label: 'Get Contents'
+                          #translateLabel: true
+                          #value: #fileGet
+                          #enabled: #hasSelection
+                      )
+                       #(#MenuItem
+                          #label: 'Insert Contents'
+                          #translateLabel: true
+                          #value: #fileInsert
+                          #enabled: #hasSelection
+                      )
+                    ) nil
+                    nil
+                )
+            )
+             #(#MenuItem
+                #label: 'View'
+                #translateLabel: true
+                #submenu: 
+                 #(#Menu
+                    
+                     #(
+                       #(#MenuItem
+                          #label: 'Details'
+                          #translateLabel: true
+                          #indication: #showingDetails
+                      )
+                       #(#MenuItem
+                          #label: 'Show Hidden Files'
+                          #translateLabel: true
+                          #indication: #showingHiddenFiles
+                      )
+                       #(#MenuItem
+                          #label: '-'
+                      )
+                       #(#MenuItem
+                          #label: 'Sort By Name'
+                          #translateLabel: true
+                          #choice: #sortByWhat
+                          #choiceValue: #name
+                      )
+                       #(#MenuItem
+                          #label: 'Sort By Type'
+                          #translateLabel: true
+                          #choice: #sortByWhat
+                          #choiceValue: #type
+                      )
+                       #(#MenuItem
+                          #label: 'Sort By Time'
+                          #translateLabel: true
+                          #choice: #sortByWhat
+                          #choiceValue: #time
+                      )
+                       #(#MenuItem
+                          #label: 'Ignore Case'
+                          #translateLabel: true
+                          #enabled: #sortByName
+                          #indication: #sortCaseless
+                      )
+                       #(#MenuItem
+                          #label: '-'
+                      )
+                       #(#MenuItem
+                          #label: 'Encoding...'
+                          #translateLabel: true
+                          #value: #fileEncoding
+                      )
+                       #(#MenuItem
+                          #label: '-'
+                      )
+                       #(#MenuItem
+                          #label: 'Update'
+                          #translateLabel: true
+                          #value: #updateCurrentDirectory
+                      )
+                    ) nil
+                    nil
+                )
+            )
+             #(#MenuItem
+                #label: 'Tools'
+                #translateLabel: true
+                #submenu: 
+                 #(#Menu
+                    
+                     #(
+                       #(#MenuItem
+                          #label: 'Unix Command'
+                          #translateLabel: true
+                          #isVisible: #systemIsUnix
+                          #value: #menuOSCommand
+                      )
+                       #(#MenuItem
+                          #label: 'DOS Command'
+                          #translateLabel: true
+                          #isVisible: #systemIsDOS
+                          #value: #menuOSCommand
+                      )
+                       #(#MenuItem
+                          #label: 'VMS Command'
+                          #translateLabel: true
+                          #isVisible: #systemIsVMS
+                          #value: #menuOSCommand
+                      )
+                       #(#MenuItem
+                          #label: '-'
+                      )
+                       #(#MenuItem
+                          #label: 'Changes Browser'
+                          #translateLabel: true
+                          #value: #openChangesBrowser
+                          #enabled: #hasSelection
+                      )
+                       #(#MenuItem
+                          #label: 'Editor'
+                          #translateLabel: true
+                          #value: #openEditor
+                          #enabled: #hasSelection
+                      )
+                       #(#MenuItem
+                          #label: 'HTML Reader'
+                          #translateLabel: true
+                          #value: #openHTMLReader
+                          #enabled: #hasSelection
+                      )
+                       #(#MenuItem
+                          #label: 'Image Inspector'
+                          #translateLabel: true
+                          #value: #openImageInspector
+                          #enabled: #hasSelection
+                      )
+                       #(#MenuItem
+                          #label: 'Image Editor'
+                          #translateLabel: true
+                          #value: #openImageEditor
+                          #enabled: #hasSelection
+                      )
+                       #(#MenuItem
+                          #label: 'File Differences...'
+                          #translateLabel: true
+                          #value: #openDiffView
+                      )
+                       #(#MenuItem
+                          #label: 'Shell Terminal'
+                          #translateLabel: true
+                          #value: #openTerminal
+                          #enabled: #systemIsUnix
+                      )
+                    ) nil
+                    nil
+                )
+            )
+             #(#MenuItem
+                #label: 'Help'
+                #translateLabel: true
+                #startGroup: #right
+                #submenu: 
+                 #(#Menu
+                    
+                     #(
+                       #(#MenuItem
+                          #label: 'Documentation'
+                          #translateLabel: true
+                          #value: #openHTMLDocument:
+                          #argument: 'tools/fbrowser/TOP.html'
+                      )
+                    ) nil
+                    nil
+                )
+            )
+          ) nil
+          nil
+      )
+
+    "Modified: / 14.8.1998 / 15:54:52 / cg"
+! !
+
+!FileBrowser methodsFor:'aspects'!
+
+currentDirectoryIsNotTop
+    ^ [currentDirectory notNil and:[currentDirectory isRootDirectory not]]
+
+    "Modified: / 4.8.1998 / 14:10:57 / cg"
+    "Created: / 14.8.1998 / 12:07:10 / cg"
+!
+
+hasSelection
+    ^ [fileListView selection size > 0]
+
+    "Created: / 4.8.1998 / 14:10:31 / cg"
+    "Modified: / 4.8.1998 / 14:10:57 / cg"
+!
+
+showingDetails
+    ^ showingDetails
+
+    "Created: / 14.8.1998 / 14:15:15 / cg"
+!
+
+showingHiddenFiles
+    ^ showingHiddenFiles
+
+    "Created: / 14.8.1998 / 14:15:44 / cg"
+!
+
+sortByWhat
+    ^ sortByWhat
+
+    "Created: / 14.8.1998 / 15:55:18 / cg"
+    "Modified: / 14.8.1998 / 15:56:08 / cg"
+!
+
+sortCaseless
+    ^ sortCaseless
+
+    "Created: / 14.8.1998 / 14:21:21 / cg"
+!
+
+systemIsDOS
+    ^ OperatingSystem isMSDOSlike
+
+    "Created: / 4.8.1998 / 13:37:28 / cg"
+!
+
+systemIsUnix
+    ^ OperatingSystem isUNIXlike
+
+    "Created: / 4.8.1998 / 13:37:13 / cg"
+!
+
+systemIsVMS
+    ^ OperatingSystem isVMSlike
+
+    "Created: / 4.8.1998 / 13:37:37 / cg"
+! !
+
 !FileBrowser methodsFor:'drag & drop'!
 
 canDrop:aCollectionOfDropObjects
@@ -391,18 +1024,32 @@
 changeDisplayMode
     "toggle from long to short listing (and vice-versa)"
 
-    showLongList := showLongList not.
+    showingDetails value:(showingDetails value not).
+    "/ showLongList := showLongList not.
     self showOrHideTabView.
     self updateCurrentDirectory
 
-    "Modified: 19.4.1997 / 09:50:14 / cg"
+    "Modified: / 4.8.1998 / 13:43:54 / cg"
 !
 
 changeDotFileVisibility
     "turn on/off visibility of files whose name starts with '.'"
 
-    showDotFiles := showDotFiles not.
+    showingHiddenFiles value:(showingHiddenFiles value not).
+    "/ showDotFiles := showDotFiles not.
     self updateCurrentDirectory
+
+    "Modified: / 4.8.1998 / 13:45:46 / cg"
+!
+
+detailsSettingChanged
+    "invoked, when detail (i.e. long / short) listing flag changed"
+
+    self showOrHideTabView.
+    self updateCurrentDirectory
+
+    "Modified: / 4.8.1998 / 13:43:54 / cg"
+    "Created: / 14.8.1998 / 14:17:49 / cg"
 !
 
 fileDoubleClick:lineNr
@@ -668,6 +1315,21 @@
 
     <resource: #programMenu>
 
+    |m|
+
+    m := self class menuPopUp.
+    m := m decodeAsLiteralArray.
+    m receiver:self.
+    ^ m.
+
+    "Modified: / 14.8.1998 / 14:09:12 / cg"
+!
+
+fileListMenu_old
+    "return the menu to show in the fileList"
+
+    <resource: #programMenu>
+
     |items m sel ns subMenu subItems|
 
     items := #(
@@ -712,10 +1374,10 @@
             itemList:items
             resources:resources.
 
-    showDotFiles ifTrue:[
+    showingHiddenFiles value "showDotFiles" ifTrue:[
         m labelAt:#changeDotFileVisibility put:(resources string:'hide hidden files')
     ].
-    showLongList ifTrue:[
+    showingDetails value "showLongList" ifTrue:[
         m labelAt:#changeDisplayMode put:(resources string:'display short list')
     ].
 
@@ -757,7 +1419,8 @@
     ^m
 
     "Modified: / 16.1.1998 / 16:42:59 / stefan"
-    "Modified: / 27.7.1998 / 13:08:12 / cg"
+    "Modified: / 4.8.1998 / 13:45:56 / cg"
+    "Created: / 13.8.1998 / 20:51:38 / cg"
 !
 
 filePrint
@@ -887,6 +1550,140 @@
     "Modified: / 16.1.1998 / 16:54:00 / stefan"
 !
 
+newHardLink
+    "ask for and create a hard link (unix only)"
+
+    |sel box orgName1 name1 name2 f1 f2 f d err nm here l1 if1 if2|
+
+    sel := self getSelectedFileName.
+
+    orgName1 := ''.
+    (sel size > 0) ifTrue:[
+        (currentDirectory construct:sel) isDirectory ifFalse:[
+            orgName1 := sel
+        ]
+    ].
+
+    name1 := orgName1 asValue.
+    name2 := '' asValue.
+
+    box := DialogBox new.
+    (box addTextLabel:'Create hard link from:') adjust:#left.
+    if1 := box addFilenameInputFieldOn:name1 in:here tabable:true.
+    (box addTextLabel:'to:') adjust:#left.
+    if2 := box addFilenameInputFieldOn:name2 in:here tabable:true.
+
+    box addAbortButton; addOkButton.
+
+    orgName1 size > 0 ifTrue:[
+        box focusOnField:if2.
+    ].
+    box showAtPointer.
+
+    box accepted ifTrue:[
+        name1 := name1 value.
+        (name1 size == 0) ifTrue:[
+            err := 'no name entered'.
+        ] ifFalse:[
+            f1 := name1 asFilename.
+            name2 := name2 value.
+            (name2 size == 0) ifTrue:[
+                err := 'no name entered'.
+            ] ifFalse:[
+                f2 := name2 asFilename.
+                f2 exists ifTrue:[
+                    err := '''%2'' already exists'.
+                ] ifFalse:[
+                    f1 exists ifFalse:[
+                        err := '''%1'' does not exist'.
+                    ] ifTrue:[
+                        f1 isDirectory ifTrue:[
+                            err := '''%1'' is a directory'.
+                        ] ifFalse:[
+                            ErrorSignal handle:[:ex |
+                                err := ex errorString
+                            ] do:[
+                                OperatingSystem createHardLinkFrom:name1 to:name2
+                            ]
+                        ]
+                    ]
+                ]
+            ]
+        ].
+
+        err notNil ifTrue:[
+            self warn:(resources string:err with:(name1 ? '') asText allBold with:(name2 ? '') asText allBold).
+            ^ self
+        ].
+    ].
+
+    "Modified: / 13.8.1998 / 21:47:01 / cg"
+!
+
+newSoftLink
+    "ask for and create a soft link (unix only)"
+
+    |sel box orgName1 name1 name2 f1 f2 f d err nm here l1 if1 if2|
+
+    sel := self getSelectedFileName.
+
+    orgName1 := ''.
+    (sel size > 0) ifTrue:[
+        orgName1 := sel
+    ].
+
+    name1 := orgName1 asValue.
+    name2 := '' asValue.
+
+    box := DialogBox new.
+    (box addTextLabel:'Create symbolic link to:') adjust:#left.
+    if1 := box addFilenameInputFieldOn:name1 in:here tabable:true.
+    (box addTextLabel:'as:') adjust:#left.
+    if2 := box addFilenameInputFieldOn:name2 in:here tabable:true.
+
+    box addAbortButton; addOkButton.
+
+    orgName1 size > 0 ifTrue:[
+        box focusOnField:if2.
+    ].
+    box showAtPointer.
+
+    box accepted ifTrue:[
+        name1 := name1 value.
+        (name1 size == 0) ifTrue:[
+            err := 'no name entered'.
+        ] ifFalse:[
+            f1 := name1 asFilename.
+            name2 := name2 value.
+            (name2 size == 0) ifTrue:[
+                err := 'no name entered'.
+            ] ifFalse:[
+                f2 := name2 asFilename.
+                f2 exists ifTrue:[
+                    err := '''%2'' already exists'.
+                ] ifFalse:[
+                    f1 exists ifFalse:[
+                        err := '''%1'' does not exist (link created anyway)'.
+                    ].
+                    ErrorSignal handle:[:ex |
+                        err := ex errorString
+                    ] do:[
+                        OperatingSystem createSymbolicLinkFrom:name1 to:name2
+                    ]
+                ]
+            ]
+        ].
+
+        err notNil ifTrue:[
+            self warn:(resources string:err with:(name1 ? '') asText allBold with:(name2 ? '') asText allBold).
+            ^ self
+        ].
+    ].
+
+    "Modified: / 13.8.1998 / 21:26:59 / cg"
+    "Created: / 13.8.1998 / 21:47:14 / cg"
+!
+
 openAppletViewer
     |numItems|
 
@@ -1024,6 +1821,26 @@
     "Modified: 20.5.1996 / 20:30:58 / cg"
 !
 
+openImageEditor
+    |img path|
+
+    self selectedFilesDo:[:fileName |
+        path := currentDirectory filenameFor:fileName.
+        path isDirectory ifFalse:[
+            img := Image fromFile:(path pathName).
+            img notNil ifTrue:[
+                img edit
+            ] ifFalse:[
+                self warn:'unknown format: ' , fileName
+            ]
+        ]
+    ].
+
+    "Modified: / 17.9.1995 / 17:41:24 / claus"
+    "Modified: / 18.9.1997 / 17:05:04 / stefan"
+    "Created: / 13.8.1998 / 22:07:09 / cg"
+!
+
 openImageInspector
     |img path|
 
@@ -1075,7 +1892,7 @@
 showOrHideTabView
     "depending on the showLongList setting, show or hde the tabSpec view"
 
-    showLongList ifTrue:[
+    showingDetails value "showLongList" ifTrue:[
         tabRulerView isNil ifTrue:[
             self createTabRulerIn:scrollView superView.
         ].
@@ -1099,7 +1916,7 @@
     tabSpec := nil.
 
     "Created: / 19.4.1997 / 09:50:02 / cg"
-    "Modified: / 27.7.1998 / 20:31:03 / cg"
+    "Modified: / 4.8.1998 / 13:44:14 / cg"
 ! !
 
 !FileBrowser methodsFor:'help '!
@@ -1193,7 +2010,7 @@
 
 initialize
     |frame spacing halfSpacing v topFrame labelFrame filterModel
-     buttonPanel img|
+     buttonPanel img mH menuPanel|
 
     super initialize.
 
@@ -1207,13 +2024,22 @@
     "
      showing long or short by default
     "
-    showLongList := resources at:'LONG_LIST' default:false.
+    "/ showLongList := resources at:'LONG_LIST' default:false.
+    showingDetails := (resources at:'LONG_LIST' default:false) asValue.
+    showingDetails onChangeSend:#detailsSettingChanged to:self.
 
     "
      show hidden files or not ?
     "
-    showDotFiles := resources at:'SHOW_DOT_FILES' default:false.
-
+    "/ showDotFiles := resources at:'SHOW_DOT_FILES' default:false.
+    showingHiddenFiles := (resources at:'SHOW_DOT_FILES' default:false) asValue.
+    showingHiddenFiles onChangeSend:#updateCurrentDirectory to:self.
+
+    sortByWhat := #name asValue.
+    sortByWhat onChangeSend:#sortChanged to:self.
+
+    sortCaseless := (Filename isCaseSensitive not) asValue.
+    sortCaseless onChangeSend:#updateCurrentDirectory to:self.
 
     lockUpdate := false.
 
@@ -1237,9 +2063,16 @@
     myName := (resources string:self class name).
     self label:myName.
 
+    menuPanel := MenuPanel in:self.
+    menuPanel verticalLayout:false.
+    menuPanel receiver:self.
+    menuPanel menu:(self pullDownMenu).
+    mH := menuPanel preferredExtent y.
+    menuPanel origin:(0.0 @ 0.0) corner:(1.0 @ mH).
+
     labelFrame := View 
-                        origin:(0.0 @ 0.0)
-                        corner:(1.0 @ (font height * 2))
+                        origin:(0.0 @ mH)
+                        corner:(1.0 @ (font height * 2 + mH))
                         in:self.
 
     styleSheet name = #st80 ifTrue:[
@@ -1262,7 +2095,7 @@
     filterModel := '*' asValue.
     filterField := EditField in:labelFrame.
     filterField 
-        origin:[((width // 4 * 3) + halfSpacing) @ halfSpacing]
+        origin:[((width // 4 * 3) + halfSpacing) @ (halfSpacing)]
         corner:(1.0 @ (filterField heightIncludingBorder + halfSpacing + halfSpacing) ).
     filterField rightInset:halfSpacing.
     filterField model:filterModel.
@@ -1285,13 +2118,14 @@
 
     labelView := FilenameEditField in:labelFrame.
     labelView 
-        origin:(halfSpacing @ halfSpacing)
+        origin:(halfSpacing @ (halfSpacing))
         extent:[((width // 4 * 3) - spacing - borderWidth)
                 @
                 (filterField heightIncludingBorder)
                 "(font height + font descent)"
                ].
-    labelView menu:#labelMenu; aspect:#path; changeMessage:#pathChanged:.
+    labelView menu:#labelMenu; 
+            aspect:#path; changeMessage:#pathChanged:.
     labelView model:self.
     labelView backgroundColor:(labelFrame viewBackground).
     labelFrame model:self; menu:#labelMenu.
@@ -1324,7 +2158,7 @@
 "/                 corner:(1.0 @ 1.0)
 "/                     in:self.
 
-    frame := VariableVerticalPanel origin:0.0@0.0 corner:1.0@1.0 in:self.
+    frame := VariableVerticalPanel origin:0.0@mH corner:1.0@1.0 in:self.
     frame topInset:labelFrame height.
     commandView notNil ifTrue:[
         frame bottomInset:(commandView height + spacing + spacing)
@@ -1399,7 +2233,7 @@
 
     "Modified: / 6.9.1995 / 20:26:06 / claus"
     "Modified: / 16.9.1997 / 14:52:46 / stefan"
-    "Modified: / 1.8.1998 / 17:39:22 / cg"
+    "Modified: / 14.8.1998 / 18:06:51 / cg"
 !
 
 initializeCommandViewIn:frame
@@ -1501,6 +2335,99 @@
     "Created: 24.7.1997 / 18:13:46 / cg"
 ! !
 
+!FileBrowser methodsFor:'menu actions'!
+
+menuExit
+    self closeRequest
+
+    "Created: / 4.8.1998 / 13:41:38 / cg"
+!
+
+menuOSCommand
+    self fileExecute
+
+    "Created: / 4.8.1998 / 14:06:54 / cg"
+!
+
+menuOpen
+    "same as a double-click"
+
+    "Modified: / 4.8.1998 / 13:42:14 / cg"
+!
+
+menuShowFileBrowserDocumentation
+
+    "Created: / 4.8.1998 / 14:03:57 / cg"
+!
+
+openAboutThisApplication
+    "opens an about box for this application."
+
+    |rev box myClass clsRev image msg|
+
+    rev := ''.
+    myClass := self class.
+
+    (clsRev := myClass revision) notNil ifTrue: [rev := '  (rev: ', clsRev printString, ')'].
+
+    msg := '\' withCRs , myClass name asBoldText, rev.
+
+    AboutBox isNil ifTrue:[
+        "/ this handles bad installations of ST/X,
+        "/ where the AboutBox is missing.
+        "/ (May vanish in the future)
+        ^ self information:msg
+    ].
+
+    box := AboutBox title:msg.
+
+    image := self class defaultIcon.
+    image notNil ifTrue:[
+        box image:image
+    ].
+    box   label:'About This Application'.
+    box   autoHideAfter:10 with:[].
+    box   showAtPointer.
+
+    "Modified: / 14.8.1998 / 13:20:24 / cg"
+!
+
+openHTMLDocument:relativeDocPath
+    HTMLDocumentView openFullOnDocumentationFile:relativeDocPath
+
+    "Created: / 4.8.1998 / 14:06:10 / cg"
+!
+
+pullDownMenu
+    "return the top (pullDown) menu"
+
+    <resource: #programMenu>
+
+    |m|
+
+    m := self class menuSpec.
+    m := m decodeAsLiteralArray.
+    m receiver:self.
+    ^ m.
+
+    "Modified: / 14.8.1998 / 14:09:12 / cg"
+    "Created: / 14.8.1998 / 14:14:16 / cg"
+!
+
+showAboutSTX
+    ToolApplicationModel openAboutSTX
+
+    "Created: / 14.8.1998 / 13:18:41 / cg"
+!
+
+sortChanged
+Transcript show:'fBrowser:'; showCR:sortByWhat value.
+    self updateCurrentDirectory
+
+    "Created: / 14.8.1998 / 16:17:20 / cg"
+    "Modified: / 14.8.1998 / 16:44:00 / cg"
+! !
+
 !FileBrowser methodsFor:'misc user interaction'!
 
 closeRequest
@@ -1509,10 +2436,12 @@
     (self askIfModified:'contents has not been saved.\\Modifications will be lost when FileBrowser is closed.'
               yesButton:'close') 
     ifTrue:[
+        "/ self windowGroup closeDownViews.
         super closeRequest
     ]
 
     "Created: / 3.8.1998 / 19:55:06 / cg"
+    "Modified: / 4.8.1998 / 18:21:03 / cg"
 !
 
 destroy
@@ -1666,6 +2595,16 @@
 
     <resource: #programMenu>
 
+    ^ self class directoryMenuSpec.
+
+    "Modified: / 14.8.1998 / 12:11:16 / cg"
+!
+
+labelMenu_old
+    "return the popUpMenu for the path label"
+
+    <resource: #programMenu>
+
     |items menu currentIndex|
 
     items := #(
@@ -1729,6 +2668,7 @@
     ^menu.
 
     "Modified: / 21.7.1998 / 16:43:25 / cg"
+    "Created: / 14.8.1998 / 12:10:02 / cg"
 !
 
 pathChanged:newPath
@@ -1819,22 +2759,25 @@
     "setup and launch a querybox to ask for unix command.
      Then evaluate aBlock passing the command-string as argument."
 
-    |box|
+    |box osName|
+
+    osName := OperatingSystem platformName.
 
     box := FilenameEnterBox 
-		title:(resources at:'execute unix command:')
-	       okText:(resources at:'execute')
-	       action:aBlock.
+                title:(resources string:'execute %1 command:' with:osName)
+               okText:(resources string:'execute')
+               action:aBlock.
 
     fileName notNil ifTrue:[
-	self initialCommandFor:fileName into:box.
+        self initialCommandFor:fileName into:box.
     ].
     box directory:currentDirectory.
     box showAtPointer.
     box destroy.
 
-    "Modified: 7.9.1995 / 10:31:54 / claus"
-    "Modified: 16.9.1997 / 15:35:10 / stefan"
+    "Modified: / 7.9.1995 / 10:31:54 / claus"
+    "Modified: / 16.9.1997 / 15:35:10 / stefan"
+    "Modified: / 14.8.1998 / 14:12:52 / cg"
 !
 
 askIfModified:question yesButton:yesButtonText
@@ -1925,22 +2868,22 @@
 
     newCollection := aCollection species new.
     aCollection do:[:fname |
-	|ignore|
-
-	ignore := false.
-
-	((fname startsWith:'.') and:[fname ~= '..']) ifTrue:[
-	    showDotFiles ifFalse:[
-		ignore := true
-	    ]
-	].
-	ignore ifFalse:[
-	    newCollection add:fname
-	]
+        |ignore|
+
+        ignore := false.
+
+        ((fname startsWith:'.') and:[fname ~= '..']) ifTrue:[
+            showingHiddenFiles value "showDotFiles" ifFalse:[
+                ignore := true
+            ]
+        ].
+        ignore ifFalse:[
+            newCollection add:fname
+        ]
     ].
     ^ newCollection
 
-    "Modified: 21.2.1996 / 01:33:18 / cg"
+    "Modified: / 4.8.1998 / 13:46:27 / cg"
 ! !
 
 !FileBrowser methodsFor:'private - actions & command execution'!
@@ -3685,7 +4628,7 @@
     "
 
     self withReadCursorDo:[
-        |files matchPattern list passDone f up|
+        |files matchPattern list passDone f|
 
         self stopUpdateProcess.
 
@@ -3716,13 +4659,59 @@
             self information:('directory ', currentDirectory pathName, ' vanished').
             ^ self
         ].
-        files sort.
+        (sortByWhat value == #name) ifTrue:[
+            sortCaseless value == true ifTrue:[
+                files sort:[:a :b | a asLowercase < b asLowercase]
+            ] ifFalse:[
+                files sort.
+            ]
+        ] ifFalse:[
+            (sortByWhat value == #time) ifTrue:[
+                files sort:[:a :b | |f1 f2 t1 t2|
+                                f1 := (currentDirectory construct:a).
+                                f2 := (currentDirectory construct:b).
+                                t1 := f1 isSymbolicLink 
+                                        ifFalse:[f1 modificationTime]
+                                        ifTrue:[f1 linkInfo modified].
+                                t2 := f2 isSymbolicLink 
+                                        ifFalse:[f2 modificationTime]
+                                        ifTrue:[f2 linkInfo modified].
+                                t1 := t1 ? (AbsoluteTime now).
+                                t2 := t2 ? (AbsoluteTime now).
+                                t1 > t2
+                           ]
+            ] ifFalse:[
+                (sortByWhat value == #type) ifTrue:[
+                    files sort:[:a :b | |f1 f2 t1 t2 suff1 suff2|
+                                    f1 := (currentDirectory construct:a).
+                                    f2 := (currentDirectory construct:b).
+                                    t1 := f1 type ? #xbadLink. 
+                                    t2 := f2 type ? #xbadLink. 
+                                    t1 = t2 ifTrue:[
+                                        suff1 := f1 suffix.
+                                        suff2 := f2 suffix.
+                                        suff1 = suff2 ifTrue:[
+                                            sortCaseless value == true ifTrue:[
+                                                a asLowercase < b asLowercase
+                                            ] ifFalse:[
+                                                a < b
+                                            ]
+                                        ] ifFalse:[
+                                            suff1 asLowercase < suff2 asLowercase
+                                        ]
+                                    ] ifFalse:[
+                                        t1 < t2
+                                    ]
+                               ]
+                ]
+            ]
+        ].
 
         files := self withoutHiddenFiles:files.
         fileList := files copy.
 
         tabSpec isNil ifTrue:[
-            showLongList ifTrue:[
+            showingDetails value "showLongList" ifTrue:[
                 self defineTabulatorsForLongList
             ] ifFalse:[
                 self defineTabulatorsForShortList
@@ -3773,7 +4762,7 @@
             "/ the state machine
             "/
             nextState := IdentityDictionary new.
-            showLongList ifTrue:[
+            showingDetails value "showLongList" ifTrue:[
                 nextState add:(#visibleIcons -> #visibleAttributes).
                 nextState add:(#visibleAttributes -> #visibleTypes).
                 nextState add:(#visibleTypes -> #visibleImages).
@@ -3870,7 +4859,7 @@
                                 ]
                             ].
 
-                            showLongList ifTrue:[
+                            showingDetails value "showLongList" ifTrue:[
                                 len := fileNameString size.
                                 (len > 20) ifTrue:[
                                     fileNameString := (fileNameString contractTo:20)
@@ -4047,8 +5036,8 @@
 
             listUpdateProcess := nil.
 
-        ] forkAt:(up := Processor activePriority) - 1.
-        listUpdateProcess priorityRange:(up-1 to:up).
+        ] forkAt:(Processor activePriority - 1).
+
         "
          install a new check after some time
         "
@@ -4058,7 +5047,7 @@
     "Modified: / 21.9.1995 / 11:40:23 / claus"
     "Modified: / 28.4.1997 / 22:30:30 / dq"
     "Modified: / 18.9.1997 / 18:28:30 / stefan"
-    "Modified: / 8.8.1998 / 15:51:21 / cg"
+    "Modified: / 14.8.1998 / 17:59:06 / cg"
 ! !
 
 !FileBrowser methodsFor:'queries'!
@@ -4098,5 +5087,5 @@
 !FileBrowser class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libtool/FileBrowser.st,v 1.242 1998-08-12 12:46:38 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libtool/FileBrowser.st,v 1.243 1998-08-14 16:18:08 cg Exp $'
 ! !