initial checkin
authorpenk
Wed, 25 Sep 2002 10:00:32 +0200
changeset 3892 321c1729db5b
parent 3891 bd4e9d606e98
child 3893 c9b922e80f5b
initial checkin
AbstractFileApplicationNoteBookComponent.st
AbstractFileBrowser.st
DirectoryTreeBrowser.st
FileApplicationNoteBook.st
FileBrowserV2.st
FileBrowserV2PanelView.st
FileBrowserV2Tests.st
FileBrowserV2UISpecifications.st
FileDialog.st
FindFileApplication.st
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AbstractFileApplicationNoteBookComponent.st	Wed Sep 25 10:00:32 2002 +0200
@@ -0,0 +1,187 @@
+"{ Package: 'stx:libtool' }"
+
+ApplicationModel subclass:#AbstractFileApplicationNoteBookComponent
+	instanceVariableNames:'sameFileIndex item type notifyChannel'
+	classVariableNames:''
+	poolDictionaries:''
+	category:'Interface-Tools-File'
+!
+
+
+!AbstractFileApplicationNoteBookComponent class methodsFor:'defaults'!
+
+tabStringFor:aApplicationType
+
+    ^ nil
+! !
+
+!AbstractFileApplicationNoteBookComponent class methodsFor:'queries'!
+
+canOpenItem:aItem
+
+"
+    example:
+    ^ (aItem suffix == 'cc')
+"
+    ^ false
+!
+
+wantNewApplicationAnyway
+
+    ^ true
+! !
+
+!AbstractFileApplicationNoteBookComponent methodsFor:'accessing'!
+
+notifyChannel
+
+    notifyChannel isNil ifTrue:[
+        self masterApplication notNil ifTrue:[
+            notifyChannel := masterApplication notifyChannel.
+        ] ifFalse:[
+            notifyChannel := ValueHolder with:''.
+        ].
+    ].
+    ^ notifyChannel
+!
+
+sameFileIndex
+
+    ^ sameFileIndex
+!
+
+sameFileIndex:something
+
+    sameFileIndex := something.
+! !
+
+!AbstractFileApplicationNoteBookComponent methodsFor:'actions'!
+
+changeItem:aItem
+
+    ^ self item:aItem.
+!
+
+doClose
+    |master|
+
+    "/ tell the NoteBookApplication to close me
+    (master := self masterApplication) notNil ifTrue:[
+        master closeSubCanvas:self.
+    ] ifFalse:[
+        self closeRequest.
+    ].
+! !
+
+!AbstractFileApplicationNoteBookComponent methodsFor:'queries'!
+
+fileName
+
+    item notNil ifTrue:[
+        ^ item fileName.
+    ].
+    ^ nil
+!
+
+getDirWithoutFileName:aFileName
+
+    | dir |
+    aFileName isNil ifTrue:[
+        ^ aFileName.    
+    ].
+    dir := aFileName asFilename.
+    dir isDirectory ifFalse:[
+        dir := dir directory.
+    ].
+    ^ dir.
+!
+
+getTabString
+
+" get the tab string from the application list on the class side "
+
+    | stream string firstString endString|
+
+    stream := WriteStream on:''.
+    firstString := self class tabStringFor:type.
+    firstString isNil ifTrue:[
+        "/ default take the class name
+        firstString := self className.
+    ].
+    stream nextPutAll:firstString.
+    endString := self getTabStringEnd.
+    endString notNil ifTrue:[
+        stream space.
+        stream nextPutAll:endString.
+    ].
+    string := stream contents.
+    stream close.
+    ^ string.
+!
+
+getTabStringEnd
+
+" get the tab string from the application list on the class side "
+
+    | stream string|
+
+    self item notNil ifTrue:[
+        stream := WriteStream on:''.
+        stream nextPutAll:self fileName baseName.
+        stream space.
+        self sameFileIndex notNil ifTrue:[
+            stream nextPutAll:self sameFileIndex asString.
+        ].
+        string := stream contents.
+        stream close.
+        ^ string.
+    ].
+    ^ nil
+!
+
+isEmbeddedApplication
+
+     ^ self masterApplication notNil
+!
+
+isModified
+
+    ^ false
+!
+
+item
+
+    ^ item
+!
+
+item:aItem
+
+    item := aItem.
+    ^ true
+!
+
+presentation
+
+    ^ nil
+!
+
+type
+
+    ^ type
+!
+
+type:aType
+
+    type := aType
+!
+
+wantChangeAnyWay
+
+    ^ (self type == #directoryDescription)
+! !
+
+!AbstractFileApplicationNoteBookComponent class methodsFor:'documentation'!
+
+version
+    ^ '$Header: /cvs/stx/stx/libtool/AbstractFileApplicationNoteBookComponent.st,v 1.1 2002-09-25 08:00:15 penk Exp $'
+! !
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AbstractFileBrowser.st	Wed Sep 25 10:00:32 2002 +0200
@@ -0,0 +1,4156 @@
+"{ Package: 'stx:libtool' }"
+
+ApplicationModel subclass:#AbstractFileBrowser
+	instanceVariableNames:'aspects'
+	classVariableNames:'DefaultCommandPerMIME SettingsAspects RuntimeAspects
+		DirectoryBookmarks LastEnforcedNameSpace CommandHistory
+		DefaultCommandPerSuffix CommandHistorySize LastFileDiffFile'
+	poolDictionaries:''
+	category:'Interface-Tools-File'
+!
+
+AbstractFileBrowser class instanceVariableNames:'DisabledCursorImage EnabledCursorImage'
+
+"
+ The following class instance variables are inherited by this class:
+
+	ApplicationModel - ClassResources
+	Model - 
+	Object - 
+"
+!
+
+Object subclass:#Clipboard
+	instanceVariableNames:'method files'
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:AbstractFileBrowser
+!
+
+Object subclass:#CodeExecutionLock
+	instanceVariableNames:'locked'
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:AbstractFileBrowser
+!
+
+OrderedCollection subclass:#DirectoryHistory
+	instanceVariableNames:'index'
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:AbstractFileBrowser
+!
+
+OrderedSet subclass:#FilenameHistory
+	instanceVariableNames:''
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:AbstractFileBrowser
+!
+
+Object subclass:#SaveAspectItem
+	instanceVariableNames:'value isHolder'
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:AbstractFileBrowser
+!
+
+
+!AbstractFileBrowser class methodsFor:'classAccess'!
+
+filenameHistoryClass
+
+    ^ FilenameHistory
+! !
+
+!AbstractFileBrowser class methodsFor:'defaults'!
+
+UnixVNCCommand
+
+    ^ 'Xvnc'
+!
+
+commandHistory
+
+    CommandHistory isNil ifTrue:[
+        CommandHistory := OrderedCollection new.
+    ].
+    ^ CommandHistory
+!
+
+commandHistorySize
+
+    CommandHistorySize isNil ifTrue:[
+        CommandHistorySize := 50
+    ].
+    ^ CommandHistorySize
+!
+
+defaultCommandPerMIME
+
+    DefaultCommandPerMIME isNil ifTrue:[
+        self initializeDefaultCommands
+    ].
+    ^ DefaultCommandPerMIME
+!
+
+defaultFilterList
+
+    DefaultFilters isNil ifTrue:[
+        DefaultFilters := #(        '*'
+                                    '*.st' 
+                                    '*.htm*' 
+                                    '*.txt' 
+                                    '*.gif' 
+                                    '*.xpm' 
+                                    '*.jpg' 
+                                    '*.[h,c]*' 
+                                )
+    ].
+    ^ DefaultFilters.
+!
+
+directoryBookmarks
+
+    DirectoryBookmarks isNil ifTrue:[                     
+        DirectoryBookmarks := OrderedCollection new.
+        DirectoryBookmarks add:Filename homeDirectory asAbsoluteFilename.
+        DirectoryBookmarks add:Filename tempDirectory.
+        DirectoryBookmarks add:Filename currentDirectory asAbsoluteFilename.
+        Smalltalk systemPath do:[:path |
+            ((path ~= '.') and:[path asFilename exists]) ifTrue:[
+                DirectoryBookmarks add:path asFilename.
+            ]
+        ]
+    ].
+    ^ DirectoryBookmarks
+
+"/    DirectoryBookmarks := nil
+!
+
+initializeDefaultCommands
+    DefaultCommandPerMIME := Dictionary new.
+
+    DefaultCommandPerMIME at:'application/x-tar-compressed' put:'gunzip < %1 | tar tvf -'.
+    DefaultCommandPerMIME at:'application/pdf'              put:'acroread -display %2 %1'.
+
+    "
+     self initializeDefaultCommands
+    "
+!
+
+listOfRuntimeValuesToRemark
+
+    " list of all aspects that will be saved with save settings"
+
+    ^ #(
+           #filterModel
+           #enableFileHistory
+           #enableBack
+           #enableForward
+           #dirHistory
+           #fileHistory
+           #currentFileNameHolder
+      )
+!
+
+listOfSavedSettingsAspects
+
+    " list of all aspects that will be saved with save settings"
+
+    ^ #(
+           #viewDirectoriesInDirectoryContentsBrowser
+           #sortCaseless
+           #fileHistory             
+           #showDirectoryTreeHolder  
+           #showHiddenFiles          
+           #viewDescription        
+           #viewDetails              
+           #viewDirectoryDescription
+           #viewFilesInDirectoryTree
+           #viewGroup                
+           #viewOwner                
+           #viewPermissions          
+           #viewPreview              
+           #viewSize                
+           #viewTime                 
+           #viewType  
+           #enableFileHistory
+           #openMultipleApplicationsForType
+           #sortBlockHolder
+           #filenameEntryFieldVisibleHolder
+           #toolBarVisibleHolder
+      )
+!
+
+resetAspects
+
+    RuntimeAspects := nil.
+    SettingsAspects := nil.
+
+"
+    self resetAspects
+"
+!
+
+runtimeAspects
+
+    RuntimeAspects isNil ifTrue:[
+        RuntimeAspects := Dictionary new.
+    ].
+    ^ RuntimeAspects
+!
+
+settingsAspects
+
+    SettingsAspects isNil ifTrue:[
+        SettingsAspects := Dictionary new.
+    ].
+    ^ SettingsAspects
+! !
+
+!AbstractFileBrowser class methodsFor:'image'!
+
+DisabledCursorImage
+
+    DisabledCursorImage isNil ifTrue:[
+        DisabledCursorImage := Image fromFile:'xpmBitmaps/cursors/no_entry.xpm'
+    ].
+    ^ DisabledCursorImage
+!
+
+EnabledCursorImage
+
+    EnabledCursorImage isNil ifTrue:[
+        EnabledCursorImage := Image fromFile:'xpmBitmaps/cursors/double_crossHair.xpm'
+    ].
+    ^ EnabledCursorImage
+! !
+
+!AbstractFileBrowser class methodsFor:'image specs'!
+
+clearHistoryIcon
+    ^ Icon deleteIcon
+!
+
+closeIcon
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self closeIcon inspect
+     ImageEditor openOnClass:self andSelector:#closeIcon
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'AbstractFileBrowser class closeIcon'
+        ifAbsentPut:[(Depth8Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ H@@@@@@@@@@@@B@ @@@@@@@@@@@@HB@ @@@@@@@@@B@ H@@@@@@@@@@@@@@ HB@@@@@@@B@ H@@@@@@@@@
+@@@@@@@B@ H@@@@B@ H@@@@@@@@@@@@@@@@@@@HB@ @B@ H@@@@@@@@@@@@@@@@@@@@@@ HB@ H@@@@@@@@@@@@@@@@@@@@@@@@B@ H@@@@@@@@@@@@@@@@@
+@@@@@@@B@ HB@ @@@@@@@@@@@@@@@@@@@@@B@ H@@ HB@@@@@@@@@@@@@@@@@@@B@ H@@@@B@ H@@@@@@@@A@@@@@@@B@ H@@@@@@@HB@ @@@@@@@@@@@@@B
+@ H@@@@@@@@@@ HB@@@@@@@@@@@@@ H@@@@@@@@@@@@B@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@A@@@@@@@@@@@@@@@@@@@@@@@@@PD@@P@@
+@@DA@@@@@PD@@@DA@@@@@P@@@@D@@@D@@@D@@P@@@@D@@@D@@@D@@@@A@@@A@@@A@@@A@@@A@PDA@@@A@@@@@P@@@P@@@P@@@@D@@P@@@@@@@@DA@@DA@@@A
+@P@@@PD@@@@A@P@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; colorMapFromArray:#[255 255 255 0 0 0 255 0 0]; mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@A C@A0G@@8N@@\\@@N8@@G0@@C @@G0@@N8@@\\B@8N@A0G@A C@@@@@A@@@MFL0QIQHQII8QIE@M&X0@@@@') ; yourself); yourself]
+!
+
+copyIcon
+    <resource: #programImage>
+
+    ^ ToolbarIconLibrary copy20x20Icon "copy28x28Icon"
+!
+
+cutIcon
+    <resource: #programImage>
+
+    ^ ToolbarIconLibrary cut20x20Icon2 "cut28x28Icon"
+!
+
+deleteIcon
+    <resource: #programImage>
+
+    ^ ToolbarIconLibrary erase20x20Icon "/ delete28x28Icon
+!
+
+diffIcon
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self diffIcon inspect
+     ImageEditor openOnClass:self andSelector:#diffIcon
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'AbstractFileBrowser class diffIcon'
+        ifAbsentPut:[(Depth8Image new) width: 26; height: 22; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+@@@@@@@@A@PDA@PDA@PD@@@@@@@@@@@@@@@@@@@@@@@DA XFA XFA P@@@@@@@@@@@@@@@@@@@@@@@PFA XF@@@@@@@@@@@@@@@@@@@@@@@@@@@@A@XFA @F
+A XD@@@@@@@@@@@@@@@@@@@@@@@DA X@A XFA P@@@@@@@@@@@@@@@@@@@@@@@PFA @FA XFA@@@@@@@@@@@@@@@@@@@@@@@A@XF@@XFA XD@@@@@@@@@@@@
+@@@@@@@@@@@DA X@A XFA P@@@@@@@@@@@@@@@@@@@@@@@PFA X@A XFA@@@@@@@@@@@@@@@@@@@@@@@A@XFA X@@@@@@@@@@@@@@@@@@@@@@@@@@@@DA XF
+A XFA P@@@@@@@@@@@@@@@@@@@@@@@PFA XFA XFA@@@@@@@@@@@@@@@@@@@@@@@A@PDA@PDA@PD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@b') ; colorMapFromArray:#[0 0 0 129 129 129 0 0 0 194 194 194 132 132 132 198 198 198 255 255 255]; mask:((Depth1Image new) width: 26; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@?8@@@O>@@@C? @@@?<@@@O> @@C?(@@@?:@@@O> @@C?8@@@??@@@O>8@@C?''@@@?80@@@@@@@@T[@@@DI@@@GSX@@BT$@@@%I@@@IRP@@A4$@@@@@@@@@@a') ; yourself); yourself]
+!
+
+fileInIcon
+    <resource: #programImage>
+
+    ^ ToolbarIconLibrary fileIn20x20Icon
+!
+
+goHomeIcon
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self goHomeIcon inspect
+     ImageEditor openOnClass:self andSelector:#goHomeIcon
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'AbstractFileBrowser class goHomeIcon'
+        ifAbsentPut:[(Depth4Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(4 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+@@@@@@@@@@@@@@@@@@@@@@H@@@@@@@@@@@@@I4@@@@@@@@@@@@H"]@@@@@@@@@@@H''A7P@@@@@@@@@H''FA]D@@@@@@@@I7FC W]@@@@@@@I7FCL8DWP@@@@@
+@''FCL3NA]D@@@@H''FCL3L3 WQ@@@I7FCL3L3L8E7PDPQFCL1DQL3"@@DQADXL1DQDSNH@@P@@@ 1EUUQL8 @@@@@BCDUY&D3"@@@@@@HLQU&XSNH@@@@@@ 1
+EVY!!L8 @@@@@BCDUY&D3"@@@@@@HLQU&XSNH@@@@@@ 1EVY!!L8 @@@@@BCDUY&D3"@@@@@@@@@@@@@@@@@@b') ; colorMapFromArray:#[0 0 0 64 0 0 255 0 0 255 255 255 129 0 0 80 194 89 60 120 60 194 0 0 161 161 161]; mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@A@@@C @FG0@FO8@F_<@F?>@G??@G?? G??0O??8_??<???<???<G??0G??0G??0G??0G??0G??0G??0G??0G??0') ; yourself); yourself]
+!
+
+hexToggle22x22Icon
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self hexToggle22x22Icon inspect
+     ImageEditor openOnClass:self andSelector:#hexToggle22x22Icon
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'AbstractFileBrowser class hexToggle22x22Icon'
+        ifAbsentPut:[(Depth8Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@EAPTEAPTEAPTE@@@@@@@@@@@@@@@@AP@@@@T@@@@EAP@@@@@@@@@@
+@@@@@@TEAP@E@@TEAPT@@@@@@@@@@@@@@@@EAP@@AP@@APTE@@@@@@@@@@@@@@@@APTE@@T@APTEAP@@@@@@@@@@@@@@@@T@@@@E@@TEAPT@@@@@@@@@@@@@
+@@@EAPTEAPTEAPTE@@@@@@@@@@@@@@@@AP@@@@T@@@@EAP@@@@@@@@@@@@@@@@T@AP@E@@T@APT@@@@@@@@@@@@@@@@E@@@@AP@@@@TE@@@@@@@@@@@@@@@@
+AP@E@@T@AP@EAP@@@@@@@@@@@@@@@@T@AP@E@@@@APT@@@@@@@@@@@@@@@@EAPTEAPTEAPTE@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; colorMapFromArray:#[0 0 0 105 133 190 129 129 129 194 194 194 255 0 0 255 255 255]; mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@A?>@A?>@A?>@A?>@A?>@A?>@A?>@A?>@A?>@A?>@A?>@A?>@A?>@A?>@A?>@@@@@B''Q@B$J@C&D@B$J@B''Q@') ; yourself); yourself]
+!
+
+historyIcon
+    <resource: #programImage>
+
+    ^ ToolbarIconLibrary history20x20Icon "/ history28x28Icon
+!
+
+homeIcon
+    <resource: #programImage>
+
+    ^ ToolbarIconLibrary home28x28Icon
+!
+
+htmlReloadIcon
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self htmlReloadIcon inspect
+     ImageEditor openOnClass:self andSelector:#htmlReloadIcon
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'AbstractFileBrowser class htmlReloadIcon'
+        ifAbsentPut:[(Depth2Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+@@@@@@@@@@@UT@@@@@EU@D@@@@UT@@@H@AUP@@@@@EU@@@@@@EU@@@@E@EU@@@@@@EU@@@@@AUUT@@@@@UUP@@@@@EU@@@@@@AT@@@@@@@P@@@@H@@@@@@@@
+@@@@@@@@@@@@@@@H@@@@@@@@@@@@@@@G@@@@@@@J@@@@@@@I@@@@@@@@') ; colorMapFromArray:#[0 0 0 0 129 0]; mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@G<C@_?C@??#A?C3C>@;G<@KG<@CG<@C??$C_?NCO>_CG<?#C9?3A3?;@''??@@?#P@?C\A?COC>CG?<CC?8C@? C') ; yourself); yourself]
+!
+
+leftArrow
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self leftArrow inspect
+     ImageEditor openOnClass:self andSelector:#leftArrow
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'AbstractFileBrowser class leftArrow'
+        ifAbsentPut:[(Depth8Image new) width: 24; height: 24; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@D@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@PH@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@A@0D@@@@@@@@@@@@@@@@@@@@@@@@@@@DDAPH@@@@@@@@@@@@@@@@@@@@@@@@@@PX@A0D@@@@@@@@@@@@@@@@@@@@@@@@AB@@IB HK
+@0LA@PDK@@@@@@@@@@@@@@DL@@@MC <P@@@@DPLR@@@@@@@@@@@@@PX@@ALTEP8PDQDVE0\R@@@@@@@@@@@AAADQD1PUEQTNF@$SFP(R@@@@@@@@@@@KB!!P[
+GAPUEQT]GQ4]GP(R@@@@@@@@@@@@D (TG!!0TEA,_G1<[H@(R@@@@@@@@@@@@@AHJC!!< GQ4JB (JB"DK@@@@@@@@@@@@@@@RB 8^B DRD!!HRD!!HK@@@@@@@@
+@@@@@@@@D (]H H@@@@@@@@@@@@@@@@@@@@@@@@@@AHJHPD@@@@@@@@@@@@@@@@@@@@@@@@@@@@K@PH@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B0D@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@,@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') ; colorMapFromArray:#[224 224 224 0 32 64 0 32 96 32 64 96 96 128 160 64 96 128 128 160 192 32 96 128 128 160 160 160 192 224 0 96 128 0 0 0 128 128 160 64 192 192 32 160 192 64 128 192 128 192 224 192 224 224 0 0 32 96 192 224 0 160 192 0 128 192 160 224 224 96 160 192 128 192 192 64 160 192 192 192 192 32 192 192 0 192 224 0 128 160 32 192 224 64 192 224 0 192 192 0 64 96 0 64 128]; mask:((Depth1Image new) width: 24; height: 24; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@B@@@F@@@N@@@^@@@>@@A??@C??@G??@O??@O??@G??@C??@A??@@>@@@^@@@N@@@F@@@B@@@@@@@@@@@@@@@@@@') ; yourself); yourself]
+!
+
+leftArrow20x20Icon
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self leftArrow20x20Icon inspect
+     ImageEditor openOnClass:self andSelector:#leftArrow20x20Icon
+     Icon flushCachedIcons
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'AbstractFileBrowser class leftArrow20x20Icon'
+        ifAbsentPut:[(Depth8Image new) width: 20; height: 20; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@P@@@@@@@@@@@@@@@@@@@@@@@@DB@@@@@@@@@@@@@@@@@@@@@@@A@0D@@@@@@@@@@@@@@@@@@@@@@PPE
+@ @@@@@@@@@@@@@@@@@@@@DF@@\A@@@@@@@@@@@@@@@@@@@AB@@IB HK@0LA@PDK@@@@@@@@@P0@@@4NC1@@@@@Q@1H@@@@@@@DF@@@SEATNDADQE!!\GD @@
+@@@AAADQD1PUEQTNF@$SFP(R@@@@@@,JEA,\EATUEQ4]GQ4]B!!H@@@@@@AHJEA8\EAP[G1<_F2@JD @@@@@@@AHJC!!< GQ4JB (JB"DK@@@@@@@@@AHJC!!8J
+@QHRD!!HRD ,@@@@@@@@@@AHJGRHB@@@@@@@@@@@@@@@@@@@@@AHJHPD@@@@@@@@@@@@@@@@@@@@@@@,A@ @@@@@@@@@@@@@@@@@@@@@@@@,A@@@@@@@@@@@@
+@@@@@@@@@@@@@@,@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; colorMapFromArray:#[224 224 224 0 32 64 0 32 96 32 64 96 96 128 160 64 96 128 128 160 192 32 96 128 128 160 160 160 192 224 0 96 128 0 0 0 128 128 160 64 192 192 32 160 192 64 128 192 128 192 224 192 224 224 0 0 32 96 192 224 0 160 192 0 128 192 160 224 224 96 160 192 128 192 192 64 160 192 192 192 192 32 192 192 0 192 224 0 128 160 32 192 224 64 192 224 0 192 192 0 64 96 0 64 128]; mask:((Depth1Image new) width: 20; height: 20; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@B@@@F@@@N@@@^@@@>@@A??@C??@G??@O??@O??@G??@C??@A??@@>@@@^@@@N@@@F@@@B@@@@@@') ; yourself); yourself]
+!
+
+leftArrow20x20PlusMenuIcon
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self leftArrow20x20PlusMenuIcon inspect
+     ImageEditor openOnClass:self andSelector:#leftArrow20x20PlusMenuIcon
+     Icon flushCachedIcons
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'AbstractFileBrowser class leftArrow20x20PlusMenuIcon'
+        ifAbsentPut:[(Depth8Image new) width: 20; height: 20; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@D@@@@@@@@@@@@@@@@@@@@@@@@A@ @@@@@@@@@@@@@@@@@@@@@@@PLA@@@@@@@@@@@@@@@@@@@@@@DD
+APH@@@@@@@@@@@@@@@@@@@@AA @G@P@@@@@@@@@@@@@@@@@@@P @BP(BB0LC@PDAB0@@@@@@@@DL@@@MC <P@@@@DPLR@@@@@@@AA @@D1PUC!!@QDQXWA1H@
+@@@@@PPQDQLTEQTUC!! ID1$JD @@@@@KB!!P[GAPUEQT]GQ4]GP(R@@@@@@@RB!!P^GAPTF1<_G1, B!!H@@@@@@@@RB 8_HA4]B (JB (!!B0@@@@@@@@@RB 8^
+B DRD!!HRD!!HK@@@@@@@@@@@RB!!4"@ @@@@@@@@@@@@@@@@@@@@@RB"DA@@@@@@@@@@@KB0,KB0,K@@@K@PH@@@@@@@@@@@@KB0,KB0@@@@@K@P@@@@@@@@@@
+@@@KB0,@@@@@@@@K@@@@@@@@@@@@@@@K@@@@@@@@@@@@@@@@@@@@@@@a') ; colorMapFromArray:#[224 224 224 0 32 64 0 32 96 32 64 96 96 128 160 64 96 128 128 160 192 32 96 128 128 160 160 160 192 224 0 96 128 0 0 0 128 128 160 64 192 192 32 160 192 64 128 192 128 192 224 192 224 224 0 0 32 96 192 224 0 160 192 0 128 192 160 224 224 96 160 192 128 192 192 64 160 192 192 192 192 32 192 192 0 192 224 0 128 160 32 192 224 64 192 224 0 192 192 0 64 96 0 64 128]; mask:((Depth1Image new) width: 20; height: 20; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@A@@@C@@@G@@@O@@@_@@@?? A?? C?? G?? G?? C?? A?? @?? @_@@@O@@?''@@_C@@NA@@D@@@') ; yourself); yourself]
+!
+
+leftArrowPlusMenu
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self leftArrowPlusMenu inspect
+     ImageEditor openOnClass:self andSelector:#leftArrowPlusMenu
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'AbstractFileBrowser class leftArrowPlusMenu'
+        ifAbsentPut:[(Depth8Image new) width: 24; height: 24; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@D@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@PH@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@A@0D@@@@@@@@@@@@@@@@@@@@@@@@@@@DDAPH@@@@@@@@@@@@@@@@@@@@@@@@@@PX@A0D@@@@@@@@@@@@@@@@@@@@@@@@AB@@IB HK
+@0LA@PDK@@@@@@@@@@@@@@DL@@@MC <P@@@@DPLR@@@@@@@@@@@@@PX@@ALTEP8PDQDVE0\R@@@@@@@@@@@AAADQD1PUEQTNF@$SFP(R@@@@@@@@@@@KB!!P[
+GAPUEQT]GQ4]GP(R@@@@@@@@@@@@D (TG!!0TEA,_G1<[H@(R@@@@@@@@@@@@@AHJC!!< GQ4JB (JB"DK@@@@@@@@@@@@@@@RB 8^B DRD!!HRD!!HK@@@@@@@@
+@@@@@@@@D (]H H@@@@@@@@@@@@@@@@@@@@@@@@@@AHJHPD@@@@@@@@@@@@@@@@@@@@@@@@@@@@K@PH@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B0D@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@,@@@@@@@@KB0,KB0,K@@@@@@@@@@@@@@@@@@@@@@@@B0,KB0,@@@@@@@@@@@@@@@@@@@@@@@@@@@,KB0@@@@@@@@@@@@@@@@@@
+@@@@@@@@@@@K@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') ; colorMapFromArray:#[224 224 224 0 32 64 0 32 96 32 64 96 96 128 160 64 96 128 128 160 192 32 96 128 128 160 160 160 192 224 0 96 128 0 0 0 128 128 160 64 192 192 32 160 192 64 128 192 128 192 224 192 224 224 0 0 32 96 192 224 0 160 192 0 128 192 160 224 224 96 160 192 128 192 192 64 160 192 192 192 192 32 192 192 0 192 224 0 128 160 32 192 224 64 192 224 0 192 192 0 64 96 0 64 128]; mask:((Depth1Image new) width: 24; height: 24; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@B@@@F@@@N@@@^@@@>@@A??@C??@G??@O??@O??@G??@C??@A??@@>@@@^@@@N@@@F@@@BA?@@@>@@@\@@@H@@@@') ; yourself); yourself]
+!
+
+leftDownIcon
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self leftDownIcon inspect
+     ImageEditor openOnClass:self andSelector:#leftDownIcon
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'AbstractFileBrowser class leftDownIcon'
+        ifAbsentPut:[(Depth2Image new) width: 28; height: 28; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+UUUUUUUUUUUPAUUUUUUUP@UUUUUUUPB!!UUUUUU@B*AUUUUU@B*(UUUUUPB** UUUUPB***AUUUTB***(EUUUB****%UUUR*****UUUUU@*%UUUUUUPJ)UUUU
+UUTB*UUUUUUU@*%UUUUUUPJ)UUUUUUTB*UUUUUUU@*%UUUUUUPJ)UUUUUUTB*UUUUUUU@*$@@@@AUPJ*****)UTB******UU@******%UPJ*****)UTAUUUU
+UUUU@@@@@@@AUUUUUUUUUP@a') ; colorMapFromArray:#[255 255 255 0 0 0 40 40 100 255 0 0]; mask:((Depth1Image new) width: 28; height: 28; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+@@@@@@@@@@@@ @@@@\@@@@O @@@G<@@@C? @@A?<@@@?? @@_?<@@G?? @@C<@@@@?@@@@O0@@@C<@@@@?@@@@O0@@@C<@@@@?@@@@O0@@@C??? @???8@O?
+?>@C??? @???8@O??>@@@@@@@@@@@@@a') ; yourself); yourself]
+!
+
+leftIcon
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self leftIcon inspect
+     ImageEditor openOnClass:self andSelector:#leftIcon
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'AbstractFileBrowser class leftIcon'
+        ifAbsentPut:[(Depth2Image new) width: 28; height: 28; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUPUUUUUUUUPUUUUUUUUP%UUUUUUUP)UUUUUUUP*P@@@@@AP*$@@@@@@P*******
+*P********$********)J********U********%V*%UUUUUUUZ)UUUUUUUP*UUUUUUUUV%UUUUUUUUYUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
+UUUUUUUUUUUUUUUUUUUUUP@a') ; colorMapFromArray:#[255 255 255 0 0 0 40 40 100 255 0 0]; mask:((Depth1Image new) width: 28; height: 28; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@H@@@@F@@@@C @@@A8@@@@>@@@@_???0O???<G????C????0_???<C????@_???0C8@@@@^@@@@C @@@@X@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; yourself); yourself]
+!
+
+menuHistoryList9x20Icon
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self menuHistoryList9x20Icon inspect
+     ImageEditor openOnClass:self andSelector:#menuHistoryList9x20Icon
+     Icon flushCachedIcons
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'AbstractFileBrowser class menuHistoryList9x20Icon'
+        ifAbsentPut:[(Depth1Image new) width: 9; height: 20; photometric:(#palette); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@A0@G@@\@A0@G@@\@A0@G@@\@A0@G@A?@C8@G@@H@G<@@@@@@@@a') ; colorMapFromArray:#[255 255 255 0 0 0]; mask:((Depth1Image new) width: 9; height: 20; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@A0@G@@\@A0@G@@\@A0@G@@\@A0@G@A?@C8@G@@H@G<@@@@@@@@a') ; yourself); yourself]
+!
+
+menuHistoryListIcon
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self menuHistoryListIcon inspect
+     ImageEditor openOnClass:self andSelector:#menuHistoryListIcon
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'AbstractFileBrowser class menuHistoryListIcon'
+        ifAbsentPut:[(Depth1Image new) width: 12; height: 12; photometric:(#palette); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'??S?<O?0??C?<O?0??/?=_?0??C?<O?0') ; colorMapFromArray:#[255 255 255 0 0 0]; mask:((Depth1Image new) width: 12; height: 12; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@O@@<@C0A?8C?@G8@O@@X@@@A?8@@@') ; yourself); yourself]
+!
+
+pasteIcon
+    <resource: #programImage>
+
+    ^ ToolbarIconLibrary paste20x20Icon "/ paste28x28Icon
+!
+
+rightArrow
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self rightArrow inspect
+     ImageEditor openOnClass:self andSelector:#rightArrow
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'AbstractFileBrowser class rightArrow'
+        ifAbsentPut:[(Depth8Image new) width: 24; height: 24; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@P@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@PH@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@0PB@@@@@@@@@@@@@@@@@@@@@@@@@@@@@PTF@ @@@@@@@@@@@@@@@@@@@@@@@@@@@0\@A@H@@@@@@@@@@@@@@@@A@PDA@PDH@P\I
+@@XB@@@@@@@@@@@@@@@AA0(@@@@@B ,LB @D@ @@@@@@@@@@@@@MB \NB ,ODADRD0(@A H@@@@@@@@@@@@M@@TTEQLQE!!\WD 0K@@PB@@@@@@@@@@@MB <W
+E1\WD!!\WD!!LYDQ(B@@@@@@@@@@@AB <[D10[GQ8QG!!$QF H@@@@@@@@@@@@AA!!(ZF!!(ZE1H^FQDZ@ @@@@@@@@@@@@@A@ HB@ HB@1DYDQ(B@@@@@@@@@@@@
+@@@@@@@@@@@@@QXQF H@@@@@@@@@@@@@@@@@@@@@@@@@@0PZ@ @@@@@@@@@@@@@@@@@@@@@@@@@@@Q(B@@@@@@@@@@@@@@@@@@@@@@@@@@@@@0H@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@P@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') ; colorMapFromArray:#[224 224 224 0 32 64 0 0 0 0 64 96 32 128 160 128 160 192 32 96 128 128 192 192 0 64 64 160 192 192 192 224 224 160 192 224 96 192 224 32 64 96 160 224 224 128 192 224 96 160 192 0 160 192 0 128 192 64 192 192 64 160 192 96 192 192 32 160 192 0 128 160 192 192 192 64 224 224 0 96 128 32 192 192 64 192 224 0 192 224 0 192 192]; mask:((Depth1Image new) width: 24; height: 24; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@D@@@F@@@G@@@G @@G0@O?8@O?<@O?>@O??@O??@O?>@O?<@O?8@@G0@@G @@G@@@F@@@D@@@@@@@@@@@@@@@@@@') ; yourself); yourself]
+!
+
+rightArrow20x20Icon
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self rightArrow20x20Icon inspect
+     ImageEditor openOnClass:self andSelector:#rightArrow20x20Icon
+     Icon flushCachedIcons
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'AbstractFileBrowser class rightArrow20x20Icon'
+        ifAbsentPut:[(Depth8Image new) width: 20; height: 20; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@A@@@@@@@@@@@@@@@@@@@@@@@@@@DB@@@@@@@@@@@@@@@@@@@@@@@@@0PB@@@@@@@@@@@@@@@@@@@@@@@A
+APXB@@@@@@@@@@@@@@@@@@@@@@LG@@PB@@@@@@@@@@@A@PDA@PDH@P\I@@XB@@@@@@@@@@DGB @@@@@JB00J@@PB@@@@@@@@CP(GC (KC1@QD!!LJ@@XB@@@@
+@@@M@@TTEQLQE!!\WD 0K@@PB@@@@@@4JC1\WE1\RE1\RD1$QF H@@@@@@P(OF1L\F14^DQ8YDQ(B@@@@@@@AA!!(ZF!!(ZE1H^FQDZ@ @@@@@@@@DB@ HB@ HC
+DQ$QF H@@@@@@@@@@@@@@@@@@@DVDQ(B@@@@@@@@@@@@@@@@@@@@@0PZ@ @@@@@@@@@@@@@@@@@@@@@AF H@@@@@@@@@@@@@@@@@@@@@@@LB@@@@@@@@@@@@
+@@@@@@@@@@@@@P@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; colorMapFromArray:#[224 224 224 0 32 64 0 0 0 0 64 96 32 128 160 128 160 192 32 96 128 128 192 192 0 64 64 160 192 192 192 224 224 160 192 224 96 192 224 32 64 96 160 224 224 128 192 224 96 160 192 0 160 192 0 128 192 64 192 192 64 160 192 96 192 192 32 160 192 0 128 160 192 192 192 64 224 224 0 96 128 32 192 192 64 192 224 0 192 224 0 192 192]; mask:((Depth1Image new) width: 20; height: 20; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@D@@@F@@@G@@@G @@G0@O?8@O?<@O?>@O??@O??@O?>@O?<@O?8@@G0@@G @@G@@@F@@@D@@@@@@') ; yourself); yourself]
+!
+
+rightArrowPlusMenu
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self rightArrowPlusMenu inspect
+     ImageEditor openOnClass:self andSelector:#rightArrowPlusMenu
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'AbstractFileBrowser class rightArrowPlusMenu'
+        ifAbsentPut:[(Depth8Image new) width: 24; height: 24; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@P@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@PH@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@0PB@@@@@@@@@@@@@@@@@@@@@@@@@@@@@PTF@ @@@@@@@@@@@@@@@@@@@@@@@@@@@0\@A@H@@@@@@@@@@@@@@@@A@PDA@PDH@P\I
+@@XB@@@@@@@@@@@@@@@AA0(@@@@@B ,LB @D@ @@@@@@@@@@@@@MB \NB ,ODADRD0(@A H@@@@@@@@@@@@M@@TTEQLQE!!\WD 0K@@PB@@@@@@@@@@@MB <W
+E1\WD!!\WD!!LYDQ(B@@@@@@@@@@@AB <[D10[GQ8QG!!$QF H@@@@@@@@@@@@AA!!(ZF!!(ZE1H^FQDZ@ @@@@@@@@@@@@@A@ HB@ HB@1DYDQ(B@@@@@@@@@@@@
+@@@@@@@@@@@@@QXQF H@@@@@@@@@@@@@@@@@@@@@@@@@@0PZ@ @@@@@@@@@@@@@@@@@@@@@@@@@@@Q(B@@@@@@@@@@@@@@@@@@@@@@@@@@@@@0H@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@P@@@@@@@@@B@ HB@ HB@@@@@@@@@@@@@@@@@@@@@@@@@ HB@ H@@@@@@@@@@@@@@@@@@@@@@@@@@@HB@ @@@@@@@@@@@@@@@@@@
+@@@@@@@@@@@B@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') ; colorMapFromArray:#[224 224 224 0 32 64 0 0 0 0 64 96 32 128 160 128 160 192 32 96 128 128 192 192 0 64 64 160 192 192 192 224 224 160 192 224 96 192 224 32 64 96 160 224 224 128 192 224 96 160 192 0 160 192 0 128 192 64 192 192 64 160 192 96 192 192 32 160 192 0 128 160 192 192 192 64 224 224 0 96 128 32 192 192 64 192 224 0 192 224 0 192 192]; mask:((Depth1Image new) width: 24; height: 24; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@D@@@F@@@G@@@G @@G0@O?8@O?<@O?>@O??@O??@O?>@O?<@O?8@@G0@@G @@G@@@F@@@DA?@@@>@@@\@@@H@@@@') ; yourself); yourself]
+!
+
+rightArrowPlusMenu20x20Icon
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self rightArrowPlusMenu20x20Icon inspect
+     ImageEditor openOnClass:self andSelector:#rightArrowPlusMenu20x20Icon
+     Icon flushCachedIcons
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'AbstractFileBrowser class rightArrowPlusMenu20x20Icon'
+        ifAbsentPut:[(Depth8Image new) width: 20; height: 20; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@D@@@@@@@@@@@@@@@@@@@@@@@@@@PH@@@@@@@@@@@@@@@@@@@@@@@@CA@H@@@@@@@@@@@@@@@@@@@@@@@DE
+A H@@@@@@@@@@@@@@@@@@@@@@0\@A@H@@@@@@@@@@@DA@PDA@P AA0$@A H@@@@@@@@@@P\J@@@@@@(KC@(@A@H@@@@@@@@MB \NB ,ODADRD0(@A H@@@@@
+@@4@AQPUD1DVE1\RC@,@A@H@@@@@CP(OE1\WE1HWE1HSFQDZ@ @@@@@AB <[D10[GQ8QG!!$QF H@@@@@@@DFF!!(ZF!!(WD!!8YDQ(B@@@@@@@@@PHB@ HB@ LQ
+FQDZ@ @@@@@@@@@@@@@@@@@@@QXQF H@@@@@@@@@@@@@@@@@@@@CAA(B@@@@@@@@@@@@@@@@@@@@@@DZ@ @@@ HB@ HB@ @@@@@@@@@@@0H@@@@@@ HB@ H@
+@@@@@@@@@@@A@@@@@@@@@ HB@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@a') ; colorMapFromArray:#[224 224 224 0 32 64 0 0 0 0 64 96 32 128 160 128 160 192 32 96 128 128 192 192 0 64 64 160 192 192 192 224 224 160 192 224 96 192 224 32 64 96 160 224 224 128 192 224 96 160 192 0 160 192 0 128 192 64 192 192 64 160 192 96 192 192 32 160 192 0 128 160 192 192 192 64 224 224 0 96 128 32 192 192 64 192 224 0 192 224 0 192 192]; mask:((Depth1Image new) width: 20; height: 20; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@H@@@L@@@N@@@O@@@O @_?0@_?8@_?<@_?>@_?>@_?<@_?8@_?0@@O @@O@@@N_0@LO @HG@@@B@') ; yourself); yourself]
+!
+
+rightIcon
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self rightIcon inspect
+     ImageEditor openOnClass:self andSelector:#rightIcon
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'AbstractFileBrowser class rightIcon'
+        ifAbsentPut:[(Depth2Image new) width: 28; height: 28; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUTIUUUUUUUUB%UEUUUUUP*EP@@@@@@J)T@@@@@@B*%B*******
+*P********(J********B********P********PEUUUUUV*QEUUUUUP*PUUUUUUTJQUUUUUUUBQUUUUUUUPQUUUUUUUPAUUUUUUUTUUUUUUUUUUUUUUUUUUU
+UUUUUUUUUUUUUUUUUUUUUP@a') ; colorMapFromArray:#[255 255 255 0 0 0 50 50 100 255 0 0]; mask:((Depth1Image new) width: 28; height: 28; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@C@@@@@8@@@@O@@@@C8A????@_???8G????A????0_???<G???>A????@@@@O @@@C0@@@@8@@@@L@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; yourself); yourself]
+!
+
+searchIcon
+    <resource: #programImage>
+
+    ^ ToolbarIconLibrary search16x16Icon "/ search28x28Icon
+!
+
+shellIcon
+    <resource: #programImage>
+
+    OperatingSystem isMSDOSlike ifTrue:[
+        ^ ToolbarIconLibrary dos20x20Icon
+    ].
+    ^ ToolbarIconLibrary shell20x20Icon
+!
+
+upArrow
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self upArrow inspect
+     ImageEditor openOnClass:self andSelector:#upArrow
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'AbstractFileBrowser class upArrow'
+        ifAbsentPut:[(Depth8Image new) width: 24; height: 24; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@PH@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@A@0PE@@@@@@@@@@@@@@@@@@@@@@@@@@DFA0 DAP@@@@@@@@@@@@@@@@@@@@@@@P$@A0(HA@T@@@@@@@@@@@@@@@@@@@@AB0@@C@4N
+C0PE@@@@@@@@@@@@@@@@@@DF@@@LB@ MD@<DAP@@@@@@@@@@@@@@@PLGDQHHD1LHE@8UA@H@@@@@@@@@@@@AE!!\XA@<SD1LHEPPYF DB@@@@@@@@@@D\@Q0A
+GA4OD1LJEPD\@Q0A@ @@@@@@@@@@@@@@@!!8^C1T_A@T@@@@@@@@@@@@@@@@@@@@@E @GHATRA@T@@@@@@@@@@@@@@@@@@@@@E @GDQT_A@T@@@@@@@@@@@@@
+@@@@@@@@@P@!!H!!TJA@T@@@@@@@@@@@@@@@@@@@@@@P\#IATTA@T@@@@@@@@@@@@@@@@@@@@@@QXXFPPDF H@@@@@@@@@@@@@@@@@@@@@@ TEAPTE@ H@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') ; colorMapFromArray:#[224 224 224 0 32 64 0 0 0 96 128 160 0 96 128 0 0 32 128 160 192 192 224 224 0 160 192 128 128 160 32 192 192 128 160 160 96 192 224 0 192 224 32 192 224 32 160 192 64 224 224 160 192 224 64 192 192 0 128 192 0 192 192 0 128 160 32 64 96 64 96 128 32 96 128 0 64 128 0 64 96 192 192 192 0 32 96 32 128 192 128 192 224 64 192 224 128 192 192 160 224 224 96 192 192 96 160 192 64 160 192]; mask:((Depth1Image new) width: 24; height: 24; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@F@@@O@@@_ @@?0@A?8@C?<@G?>@O??@_?? @?0@@?0@@?0@@?0@@?0@@?0@@?0@@@@@@@@@@@@@@@@@@@@@') ; yourself); yourself]
+!
+
+upArrow20x20Icon
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self upArrow20x20Icon inspect
+     ImageEditor openOnClass:self andSelector:#upArrow20x20Icon
+     Icon flushCachedIcons
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'AbstractFileBrowser class upArrow20x20Icon'
+        ifAbsentPut:[(Depth8Image new) width: 20; height: 20; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DB@@@@@@@@@@@@@@@@@@@@@@@A@0PE@@@@@@@@@@@@@@@@@@@@@PXG
+B@PE@@@@@@@@@@@@@@@@@@DI@@\JB@PE@@@@@@@@@@@@@@@AB0@@C@4NC0PE@@@@@@@@@@@@@PX@@@0HB@4PC0PE@@@@@@@@@@DCA1DRBALSBAPNEPPB@@@@
+@@@AE!!\XA@<SD1LHEPPYF DB@@@@@Q0AG@D\GP<SD0(U@Q0AG@DB@@@@@@@@@@H^G <UG0PE@@@@@@@@@@@@@@@@E @GHATRA@T@@@@@@@@@@@@@@@@V@@\Q
+EQ<DAP@@@@@@@@@@@@@@@@D@HRHUB PE@@@@@@@@@@@@@@@@@P\#IATTA@T@@@@@@@@@@@@@@@@AE!! YA@PZ@ @@@@@@@@@@@@@@@@HEAPTEAPHB@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; colorMapFromArray:#[224 224 224 0 32 64 0 0 0 96 128 160 0 96 128 0 0 32 128 160 192 192 224 224 0 160 192 128 128 160 32 192 192 128 160 160 96 192 224 0 192 224 32 192 224 32 160 192 64 224 224 160 192 224 64 192 192 0 128 192 0 192 192 0 128 160 32 64 96 64 96 128 32 96 128 0 64 128 0 64 96 192 192 192 0 32 96 32 128 192 128 192 224 64 192 224 128 192 192 160 224 224 96 192 192 96 160 192 64 160 192]; mask:((Depth1Image new) width: 20; height: 20; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@F@@@O@@@_ @@?0@A?8@C?<@G?>@O??@_?? @?0@@?0@@?0@@?0@@?0@@?0@@?0@@@@@@@@@') ; yourself); yourself]
+!
+
+upArrowPlusMenu
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self upArrowPlusMenu inspect
+     ImageEditor openOnClass:self andSelector:#upArrowPlusMenu
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'AbstractFileBrowser class upArrowPlusMenu'
+        ifAbsentPut:[(Depth8Image new) width: 24; height: 24; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@PH@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@A@0PE@@@@@@@@@@@@@@@@@@@@@@@@@@DFA0 DAP@@@@@@@@@@@@@@@@@@@@@@@P$@A0(HA@T@@@@@@@@@@@@@@@@@@@@AB0@@C@4N
+C0PE@@@@@@@@@@@@@@@@@@DF@@@LB@ MD@<DAP@@@@@@@@@@@@@@@PLGDQHHD1LHE@8UA@H@@@@@@@@@@@@AE!!\XA@<SD1LHEPPYF DB@@@@@@@@@@D\@Q0A
+GA4OD1LJEPD\@Q0A@ @@@@@@@@@@@@@@@!!8^C1T_A@T@@@@@@@@@@@@@@@@@@@@@E @GHATRA@T@@@@@@@@@@@@@@@@@@@@@E @GDQT_A@T@@@@@@@@@@@@@
+@@@@@@@@@P@!!H!!TJA@T@@@@@@@@@@@@@@@@@@@@@@P\#IATTA@T@@@@@@@@@@@@@@@@@@@@@@QXXFPPDF H@@@@@@@@@@@@@@@@@@@@@@ TEAPTE@ H@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B@ HB@ HB@@@@@@@@@@@@@@@@@@@@@@@@@ HB@ H@@@@@@@@@@@@@@@@@@@@@@@@@@@HB@ @@@@@@@@@@@@@@@@@@
+@@@@@@@@@@@B@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') ; colorMapFromArray:#[224 224 224 0 32 64 0 0 0 96 128 160 0 96 128 0 0 32 128 160 192 192 224 224 0 160 192 128 128 160 32 192 192 128 160 160 96 192 224 0 192 224 32 192 224 32 160 192 64 224 224 160 192 224 64 192 192 0 128 192 0 192 192 0 128 160 32 64 96 64 96 128 32 96 128 0 64 128 0 64 96 192 192 192 0 32 96 32 128 192 128 192 224 64 192 224 128 192 192 160 224 224 96 192 192 96 160 192 64 160 192]; mask:((Depth1Image new) width: 24; height: 24; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@F@@@O@@@_ @@?0@A?8@C?<@G?>@O??@_?? @?0@@?0@@?0@@?0@@?0@@?0@@?0@@@A?@@@>@@@\@@@H@@@@') ; yourself); yourself]
+!
+
+vt100Terminal
+    <resource: #programImage>
+
+    ^ ToolbarIconLibrary shell20x20Icon
+! !
+
+!AbstractFileBrowser class methodsFor:'menu specs'!
+
+baseBookmarksMenuSpec
+    "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:AbstractFileBrowser andSelector:#baseBookmarksMenuSpec
+     (Menu new fromLiteralArrayEncoding:(AbstractFileBrowser baseBookmarksMenuSpec)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #label: 'Add Bookmark'
+            #translateLabel: true
+            #value: #addBookmark
+            #enabled: #currentFilesHasDirectories
+          )
+         #(#MenuItem
+            #label: 'Remove Bookmark'
+            #translateLabel: true
+            #value: #removeBookmark
+            #enabled: #hasBookmarksToRemove
+          )
+         )
+        nil
+        nil
+      )
+!
+
+directoryMenu
+    "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:AbstractFileBrowser andSelector:#directoryMenu
+     (Menu new fromLiteralArrayEncoding:(AbstractFileBrowser directoryMenu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #label: 'Up'
+            #translateLabel: true
+            #value: #doGoDirectoryUp
+          )
+         #(#MenuItem
+            #label: '-'
+          )
+         #(#MenuItem
+            #label: 'Back'
+            #translateLabel: true
+            #value: #doBack
+            #activeHelpKey: #directoryBack
+            #enabled: #enableBack
+          )
+         #(#MenuItem
+            #label: 'Forward'
+            #translateLabel: true
+            #value: #doForward
+            #activeHelpKey: #directoryBack
+            #enabled: #enableForward
+          )
+         #(#MenuItem
+            #label: '-'
+          )
+         #(#MenuItem
+            #label: 'Default'
+            #translateLabel: true
+            #value: #doGotoDefaultDirectory
+          )
+         #(#MenuItem
+            #label: 'Home'
+            #translateLabel: true
+            #value: #doGotoHomeDirectory
+          )
+         #(#MenuItem
+            #label: 'Bookmarks'
+            #translateLabel: true
+            #submenuChannel: #bookmarksMenuSpec
+          )
+         )
+        nil
+        nil
+      )
+!
+
+editMenu
+    "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:AbstractFileBrowser andSelector:#editMenu
+     (Menu new fromLiteralArrayEncoding:(AbstractFileBrowser editMenu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #label: 'Copy'
+            #translateLabel: true
+            #value: #copyInDirContentsBrowser
+            #enabled: #hasSelection
+          )
+         #(#MenuItem
+            #label: 'Cut'
+            #translateLabel: true
+            #value: #cutInDirContentsBrowser
+            #enabled: #hasSelection
+          )
+         #(#MenuItem
+            #label: 'Paste'
+            #translateLabel: true
+            #value: #pasteFiles
+            #enabled: #canPaste
+          )
+         #(#MenuItem
+            #label: 'Delete'
+            #translateLabel: true
+            #value: #deleteInDirContentsBrowser
+            #enabled: #hasSelection
+          )
+         #(#MenuItem
+            #label: '-'
+          )
+         #(#MenuItem
+            #label: 'Copy All Filenames'
+            #translateLabel: true
+            #value: #copyFileList
+            #enabled: #fileListIsNotEmpty
+          )
+         #(#MenuItem
+            #label: 'Copy Selected Filenames'
+            #translateLabel: true
+            #value: #copySelectedFilenames
+            #enabled: #hasSelection
+          )
+         )
+        nil
+        nil
+      )
+!
+
+fileMenu
+    "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:AbstractFileBrowser andSelector:#fileMenu
+     (Menu new fromLiteralArrayEncoding:(AbstractFileBrowser fileMenu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #label: 'New'
+            #translateLabel: true
+            #submenuChannel: #newMenu
+          )
+         #(#MenuItem
+            #label: 'Rename'
+            #translateLabel: true
+            #value: #renameSelection
+            #enabled: #hasSelection
+            #shortcutKeyCharacter: #Replace
+          )
+         #(#MenuItem
+            #label: '-'
+          )
+         #(#MenuItem
+            #label: 'Show File Contents'
+            #translateLabel: true
+            #value: #doShowFileContents
+          )
+         #(#MenuItem
+            #label: 'Properties...'
+            #translateLabel: true
+            #value: #doShowProperties
+            #enabled: #hasSelection
+          )
+         #(#MenuItem
+            #label: '-'
+            #isVisible: #javaSupportLoaded
+          )
+         #(#MenuItem
+            #label: 'File In'
+            #translateLabel: true
+            #value: #fileFileIn
+            #enabled: #hasSelection
+          )
+         #(#MenuItem
+            #label: 'File in to NameSpace...'
+            #translateLabel: true
+            #value: #fileFileInToNameSpace
+            #enabled: #hasSelection
+          )
+         #(#MenuItem
+            #label: '-'
+            #isVisible: #javaSupportLoaded
+          )
+         #(#MenuItem
+            #label: 'Add to Java Class Path'
+            #translateLabel: true
+            #isVisible: #javaSupportLoaded
+            #enabled: #canAddToClassPath
+          )
+         #(#MenuItem
+            #label: 'Remove from Java Class Path'
+            #translateLabel: true
+            #isVisible: #javaSupportLoaded
+            #enabled: #canRemoveFromClassPath
+          )
+         #(#MenuItem
+            #label: 'Add to Java Source Path'
+            #translateLabel: true
+            #isVisible: #javaSupportLoaded
+            #enabled: #canAddToSourcePath
+          )
+         #(#MenuItem
+            #label: 'Remove from Java Source Path'
+            #translateLabel: true
+            #isVisible: #javaSupportLoaded
+            #enabled: #canRemoveFromSourcePath
+          )
+         )
+        nil
+        nil
+      )
+!
+
+newMenu
+    "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:DirectoryTreeBrowser andSelector:#newMenu
+     (Menu new fromLiteralArrayEncoding:(DirectoryTreeBrowser newMenu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#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
+      )
+! !
+
+!AbstractFileBrowser class methodsFor:'misc'!
+
+newLock
+    ^ CodeExecutionLock new
+! !
+
+!AbstractFileBrowser methodsFor:'actions'!
+
+askForCommandFor:fileName thenDo:aBlock
+    "setup and launch a querybox to ask for unix command.
+     Then evaluate aBlock passing the command-string as argument."
+
+    |box osName|
+
+    osName := OperatingSystem platformName.
+
+    box := FilenameEnterBox 
+                title:(resources string:'Execute %1 command:' with:osName)
+               okText:(resources string:'Execute')
+               action:aBlock.
+
+    fileName notNil ifTrue:[
+        self initialCommandFor:fileName into:box.
+    ].
+    box directory:(self getDirWithoutFileName:fileName).
+    box showAtPointer.
+    box destroy.
+
+    "Modified: / 7.9.1995 / 10:31:54 / claus"
+    "Modified: / 16.9.1997 / 15:35:10 / stefan"
+    "Modified: / 14.8.1998 / 14:12:52 / cg"
+!
+
+changeFileBrowserTitleTo:aString
+
+    self application:#FileBrowserV2
+         do:#changeFileBrowserTitleTo:                            
+         withArg:aString
+!
+
+copyFileList
+
+    | fileList stream|
+    fileList := self application:#DirectoryContentsBrowser do:#descriptions.
+    stream := WriteStream on:''.
+    fileList do:[: item |
+        stream nextPutAll:(item fileName asString).
+        stream cr.
+    ].
+    self window setTextSelection:stream contents.
+    stream close.
+!
+
+copySelectedFilenames
+
+    | fileList stream|
+    fileList := self application:#DirectoryContentsBrowser do:#getFilesFromSelection.
+    fileList isEmpty ifTrue:[^ self].
+    stream := WriteStream on:''.
+    fileList do:[: file |
+        stream nextPutAll:(file asString).
+        stream cr.
+    ].
+    self window setTextSelection:stream contents.
+    stream close.
+!
+
+doAddTerminal
+
+    | item dir directories|
+
+    directories := self currentDirectories value.
+    
+    directories isEmpty ifTrue:[
+        dir :=  Filename homeDirectory
+    ] ifFalse:[
+        dir :=  directories first.
+    ].
+    
+    item := (DirectoryContentsBrowser itemClass with:dir).
+    self fileApplicationDo:#openTerminalApplication: withArg:item.
+!
+
+doExecuteCommand
+
+    | action  fileName|
+    fileName := self getFirstFileFromSelection.
+    action := [:command | 
+                self addToCommandHistory:command for:fileName.
+                self executeCommand:command.
+              ].
+    self askForCommandFor:fileName thenDo:action
+!
+
+doGoDirectoryUp
+    | upDir directories|
+
+    self enableDirectoryUp value ifFalse:[ ^ self].
+    self currentFilesAreInSameDirectory ifTrue:[
+        directories := self currentDirectories value.
+        upDir := directories first directory.
+        self currentFileNameHolder value:(OrderedCollection with:upDir).
+    ].
+!
+
+doGotoDefaultDirectory
+    self gotoFile:(Filename defaultDirectory).
+!
+
+doGotoHomeDirectory
+
+    | home |
+
+    home := Filename homeDirectory.
+    self gotoFile:home.
+!
+
+doOpenSearchFile
+
+    |item files|
+
+    item:= self getFirstItemFromSelection.
+    item isNil ifTrue:[
+        files := self currentFileNameHolder value.
+        files notEmpty ifTrue:[
+            item := DirectoryContentsBrowser itemClass with:(files first).
+        ] ifFalse:[
+            item := DirectoryContentsBrowser itemClass with:(Filename homeDirectory asAbsoluteFilename).
+        ].
+    ].
+    self openSearchFileOn:item.
+!
+
+doShowFileContents
+
+    ^ self application:#DirectoryContentsBrowser do:#doShowFileContents.
+!
+
+doShowProperties
+
+    "show long stat (file)-info"
+
+    self fileGetInfo:true
+!
+
+fileApplicationDo:selector
+
+    ^ self application:#FileApplicationNoteBook do:selector
+!
+
+fileApplicationDo:selector withArg:arg
+    ^ self application:#FileApplicationNoteBook do:selector withArg:arg 
+!
+
+fileGetInfo:longInfo 
+    "get info on selected file - show it in a box"
+
+    |string box updater|
+
+    string := self 
+                application:#DirectoryContentsBrowser
+                do:#getFileInfoStringForFirstSelectedFile:
+                withArg:longInfo.
+    string notNil ifTrue:[
+        box := InfoBox title:string.
+        updater := [
+                    [true] whileTrue:[
+                        Delay waitForSeconds:2.
+                        string := self 
+                                    application:#DirectoryContentsBrowser
+                                    do:#getFileInfoStringForFirstSelectedFile:
+                                    withArg:longInfo.
+                        box title:string
+                    ]
+                ] fork.
+        box showAtPointer.
+        updater terminate.
+        box destroy
+    ]
+!
+
+gotoFile:aFilename
+
+    self currentFileNameHolder value:(OrderedCollection with:aFilename).
+!
+
+openApplByFileItem:aItem
+
+    self fileApplicationDo:#openApplByFileItem: withArg:aItem
+!
+
+openCommandResultApplication
+
+    ^ self fileApplicationDo:#openCommandResultApplication
+!
+
+openSearchFileOn:aItem
+
+    ^ self fileApplicationDo:#openSearchFileOn: withArg:aItem
+!
+
+openTextEditorOn:aItem
+
+    ^ self fileApplicationDo:#openTextEditorOn: withArg:aItem 
+!
+
+updateAndSelect:aColOfFiles
+
+    self application:#DirectoryContentsBrowser do:#doUpdate.
+    self application:#DirectoryTreeBrowser do:#doUpdate.
+    
+    aColOfFiles notNil ifTrue:[ self currentFileNameHolder value:aColOfFiles ].
+!
+
+updateCurrentDirectory
+
+    self updateAndSelect:nil
+! !
+
+!AbstractFileBrowser methodsFor:'actions bookmarks'!
+
+addBookmark
+
+    |directories|
+
+    self currentFilesAreInSameDirectory ifFalse:[^ self].
+    directories := self currentDirectories value.
+    self addBookmark:directories.
+!
+
+addBookmark:aColOfDirectories
+    |idx bookmarks|
+
+    aColOfDirectories do:[ : path |
+        bookmarks := self class directoryBookmarks.
+        idx := bookmarks indexOf:path.
+        idx == 0 ifTrue:[
+            bookmarks addLast:path.
+        ].
+    ].
+!
+
+bookmarksMenuSpec
+    "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:#bookmarksMenuSpec
+     (Menu new fromLiteralArrayEncoding:(AbstractFileBrowser bookmarksMenuSpec)) startUp
+    "
+    <resource: #programMenu>
+
+    |menu bookmarks|
+
+    menu := self class baseBookmarksMenuSpec.
+    menu := menu decodeAsLiteralArray.
+    menu receiver:self.
+    bookmarks := self class directoryBookmarks.
+    "/ add the history items ...
+
+    bookmarks size > 0 ifTrue:[
+        menu addItem:(MenuItem labeled:'-').
+        bookmarks do:[:dirName |
+            menu addItem:((MenuItem label:dirName asString value:[
+                (self currentDirectories value includes:dirName) ifFalse:[
+                    self currentFileNameHolder value:(OrderedCollection with:dirName).
+                ].
+            ])).
+        ].
+    ].
+    ^ menu
+
+    "Modified: / 17.8.1998 / 10:13:05 / cg"
+!
+
+hasBookmarks
+    ^ self class directoryBookmarks size > 0
+!
+
+hasBookmarksToRemove
+
+    |bookmarks directories|
+
+    directories := self getDirectoriesFromSelection.
+    bookmarks := self class directoryBookmarks.
+    ^ (bookmarks size > 0 and:[directories notEmpty])
+!
+
+removeBookmark
+
+    |bookmarks directories|
+
+    bookmarks := self class directoryBookmarks.
+    bookmarks isNil ifTrue:[ ^ self].
+    directories := self getDirectoriesFromSelection.
+    directories isEmpty ifTrue:[^ self].
+    directories do:[:dir|
+        bookmarks remove:dir ifAbsent:nil.
+    ].
+! !
+
+!AbstractFileBrowser methodsFor:'actions history'!
+
+addToCommandHistory:aCommandString for:aFilename
+    |cmd suffix cmdHist|
+
+    cmdHist := self class commandHistory.
+    (aCommandString notNil and:[aCommandString notEmpty]) ifTrue:[
+        cmdHist notNil ifTrue:[
+            cmdHist addFirst:aCommandString.
+            cmdHist size > self class commandHistorySize ifTrue:[
+                cmdHist removeLast
+            ]
+        ].
+        aFilename notNil ifTrue:[
+            cmd := aCommandString copyTo:(aCommandString indexOf:Character space ifAbsent:[aCommandString size + 1])-1.
+            DefaultCommandPerSuffix isNil ifTrue:[
+                DefaultCommandPerSuffix := Dictionary new.
+            ].
+            suffix := aFilename asFilename suffix.
+            suffix notNil ifTrue:[
+                DefaultCommandPerSuffix at:suffix put:cmd.
+            ]
+        ]
+    ]
+!
+
+doBack
+
+    | fileName |
+    fileName := self dirHistory doBack.
+    fileName notNil ifTrue:[
+        self gotoFile:fileName.
+    ]
+!
+
+doForward
+
+    | fileName |
+    fileName := self dirHistory doForward.
+    fileName notNil ifTrue:[
+        self gotoFile:fileName.
+    ]
+! !
+
+!AbstractFileBrowser methodsFor:'applications'!
+
+application:aApplication do:aMethod 
+
+    |appl|
+
+    appl := self applications at:aApplication ifAbsent:nil.
+    appl notNil ifTrue:[
+        ^ appl perform:aMethod.
+    ].
+    ^ nil.
+!
+
+application:aApplication do:aMethod withArg:arg 
+    |appl|
+
+    appl := self applications at:aApplication ifAbsent:nil.
+    appl notNil ifTrue:[
+        ^ appl perform:aMethod with:arg
+    ].
+    ^ nil
+!
+
+application:aApplication do:aMethod withArg:arg1 withArg:arg2
+    |appl|
+
+    appl := self applications at:aApplication ifAbsent:nil.
+    appl notNil ifTrue:[
+        (arg1 notNil and:[arg2 notNil]) ifTrue:[
+            ^ appl perform:aMethod with:arg1 with:arg2
+        ]
+    ].
+    ^ nil
+! !
+
+!AbstractFileBrowser methodsFor:'aspects'!
+
+applications
+    "returns the list of registered applications
+    "
+    ^ aspects at:#applications
+!
+
+backgroundProcesses
+
+    ^ self aspectFor:#backgroundProcesses ifAbsent:[List new]
+!
+
+browserFileList
+
+    ^ self aspectFor:#browserFileList ifAbsent:[List new]
+!
+
+currentDirectories
+
+    " returns a Ordered Collection of all directories currently selected 
+      if only a file is selected currentDirectories holds the directory of the file
+    "
+
+    ^ self aspectFor:#currentDirectories ifAbsent:[ (OrderedCollection new) asValue ].
+!
+
+currentFileNameHolder
+
+    " returns a OrderedCollection of all files that are selected
+      if no file but a directory is selected it contains the directories 
+      in contrast to currentDirectories wich have only the directories 
+    "
+
+    ^ self aspectFor:#currentFileNameHolder ifAbsent:[(OrderedCollection with:(Filename currentDirectory asAbsoluteFilename)) asValue]
+!
+
+enableDirectoryUp
+
+    ^ self aspectFor:#enableDirectoryUp ifAbsent:[false asValue]
+!
+
+enableHome
+
+    ^ self aspectFor:#enableHome ifAbsent:[ true asValue ].
+!
+
+enableViewNoteBookApplication
+
+    ^ self aspectFor:#enableViewNoteBookApplication ifAbsent:[false asValue]
+!
+
+filterListModel
+
+    ^ self aspectFor:#filterListModel ifAbsent:[self class defaultFilterList]
+!
+
+filterModel
+
+    ^ self aspectFor:#filterModel ifAbsent:[(self filterListModel at:1) asValue]
+!
+
+hasSelection
+
+    ^ self aspectFor:#hasSelection ifAbsent:[ false asValue ].
+!
+
+notifyChannel
+
+    ^ self aspectFor:#notifyChannel ifAbsent:['' asValue]
+!
+
+selectionInFileList
+
+    ^ self aspectFor:#selectionInFileList ifAbsent:[ OrderedCollection new asValue ]
+!
+
+sortCaseless
+
+    ^ self aspectFor:#sortCaseless ifAbsent:[
+        | holder |
+        holder := (Filename isCaseSensitive not) asValue.
+        holder
+    ]
+!
+
+treeSelectionHolder
+
+    ^ self aspectFor:#treeSelectionHolder ifAbsent:[nil asValue]
+! !
+
+!AbstractFileBrowser methodsFor:'aspects handling'!
+
+aspectFor:something ifAbsent:aBlock
+    "returns the model for an aspect
+    "
+    |holder saveAspectItem|
+
+    (holder := aspects at:something ifAbsent:nil) isNil ifTrue:[
+        saveAspectItem := self settingsAspectValueFor:something.
+        saveAspectItem isNil ifTrue:[
+            saveAspectItem := self runtimeAspectValueFor:something.
+        ].
+        saveAspectItem notNil ifTrue:[
+            saveAspectItem isHolder ifTrue:[
+                holder := ValueHolder with:saveAspectItem value 
+            ] ifFalse:[
+                holder := saveAspectItem value 
+            ].
+        ] ifFalse:[
+             holder := aBlock value.
+        ].
+        holder notNil ifTrue:[        
+            aspects at:something put:holder
+        ]
+    ].
+    ^ holder
+!
+
+aspects
+    ^ aspects
+!
+
+runtimeAspectValueFor:something
+    "returns the default aspect item from the class variable RuntimeAspects
+    "
+    ^ self class runtimeAspects at:something ifAbsent:nil.
+!
+
+saveRuntimeAspectValues
+    |savedAspects dictionary value isHolder aspect|
+
+    savedAspects := self class listOfRuntimeValuesToRemark.
+    dictionary := Dictionary new.
+    savedAspects do:[ : aspectKey |
+        aspect := self perform:aspectKey.
+        isHolder := aspect isValueModel.
+        isHolder ifTrue:[value:= aspect value] ifFalse:[ value := aspect].
+        dictionary at:aspectKey 
+                   put:(SaveAspectItem withValue:value isHolder:isHolder)
+    ].
+        
+    RuntimeAspects := dictionary. 
+!
+
+saveSettingsAspectValues
+    |savedAspects dictionary value isHolder aspect|
+
+    savedAspects := self class listOfSavedSettingsAspects.
+    dictionary := Dictionary new.
+    savedAspects do:[ : aspectKey |
+        aspect := self perform:aspectKey.
+        isHolder := aspect isValueModel.
+        isHolder ifTrue:[value:= aspect value] ifFalse:[ value := aspect].
+        dictionary at:aspectKey
+                   put:(SaveAspectItem withValue:value isHolder:isHolder)
+    ].
+
+    SettingsAspects := dictionary. 
+!
+
+settingsAspectValueFor:something
+    "returns the default aspect from the class variable Aspects
+    "
+    ^ self class settingsAspects at:something ifAbsent:nil.
+! !
+
+!AbstractFileBrowser methodsFor:'aspects-history'!
+
+dirHistory
+
+    ^ self aspectFor:#dirHistory ifAbsent:[DirectoryHistory new]
+!
+
+enableBack
+
+    ^ self aspectFor:#enableBack ifAbsent:[false asValue]
+!
+
+enableFileHistory
+
+    ^ self aspectFor:#enableFileHistory ifAbsent:[false asValue]
+!
+
+enableForward
+
+    ^ self aspectFor:#enableForward ifAbsent:[false asValue]
+!
+
+fileHistory
+
+    ^ self aspectFor:#fileHistory ifAbsent:[FilenameHistory new]
+! !
+
+!AbstractFileBrowser methodsFor:'aspects-visibility'!
+
+filenameEntryFieldVisibleHolder
+
+    ^ self aspectFor:#filenameEntryFieldVisibleHolder ifAbsent:[true asValue]
+!
+
+openMultipleApplicationsForType
+
+    ^ self aspectFor:#openMultipleApplicationsForType ifAbsent:[ false asValue ].
+!
+
+showDirectoryTreeHolder
+
+    | |
+
+    ^ self aspectFor:#showDirectoryTreeHolder ifAbsent:[ true asValue ]
+!
+
+showHiddenFiles
+
+    ^ self aspectFor:#showHiddenFiles ifAbsent:[ true asValue ].
+!
+
+sortBlockHolder
+
+    ^ self aspectFor:#sortBlockHolder ifAbsent:[ #baseName asValue ].
+!
+
+toolBarVisibleHolder
+
+    ^ self aspectFor:#toolBarVisibleHolder ifAbsent:[true asValue]
+!
+
+viewDescription
+
+    ^ self aspectFor:#viewDescription ifAbsent:[ false asValue ].
+!
+
+viewDetails
+
+    ^ self aspectFor:#viewDetails ifAbsent:[ false asValue ].
+!
+
+viewDirectoriesInDirectoryContentsBrowser
+
+    ^ self aspectFor:#viewDirectoriesInDirectoryContentsBrowser ifAbsent:[ false asValue ].
+!
+
+viewDirectoryDescription
+
+    ^ self aspectFor:#viewDirectoryDescription ifAbsent:[ true asValue ].
+!
+
+viewFilesInDirectoryTree
+
+    ^ self aspectFor:#viewFilesInDirectoryTree ifAbsent:[ false asValue ].
+!
+
+viewGroup
+
+    ^ self aspectFor:#viewGroup ifAbsent:[ false asValue ].
+!
+
+viewNoteBookApplicationHolder
+
+    ^ self aspectFor:#viewNoteBookApplicationHolder ifAbsent:[ false asValue].
+!
+
+viewOwner
+
+    ^ self aspectFor:#viewOwner ifAbsent:[ false asValue ].
+!
+
+viewPermissions
+
+    ^ self aspectFor:#viewPermissions ifAbsent:[ false asValue ].
+!
+
+viewPreview
+
+    ^ self aspectFor:#viewPreview ifAbsent:[ false asValue ].
+!
+
+viewSize
+
+    ^ self aspectFor:#viewSize ifAbsent:[ false asValue ].
+!
+
+viewTime
+
+    ^ self aspectFor:#viewTime ifAbsent:[ false asValue ].
+!
+
+viewType
+
+    ^ self aspectFor:#viewType ifAbsent:[ false asValue ].
+! !
+
+!AbstractFileBrowser methodsFor:'background processing'!
+
+executeCommand:cmd
+
+    self executeCommand:cmd inDirectory:nil
+!
+
+executeCommand:cmd inDirectory:aDir
+
+    | nameString executionBlock|
+
+    executionBlock := self getExecutionBlockForCommand:cmd inDirectory:aDir.
+    nameString := 'Command> ', cmd.
+    self makeExecutionResultProcessFor:executionBlock withName:nameString.
+!
+
+getExecutionBlockForCommand:cmd
+
+    ^ self getExecutionBlockForCommand:cmd inDirectory:nil
+!
+
+getExecutionBlockForCommand:cmd inDirectory:aDir
+
+    | dir dirs|
+
+    dir := aDir.
+    aDir isNil ifTrue:[
+        dirs := self getDirectoriesFromSelection.
+        dirs size ~= 1 ifTrue:[ ^ self].
+        dir := dirs anElement.
+    ].
+    ^ [:stream| stream notNil ifTrue:[
+            OperatingSystem 
+                executeCommand:cmd
+                inputFrom:nil 
+                outputTo:stream 
+                errorTo:stream 
+                inDirectory:dir
+                onError:[:status| false].
+        ]
+    ].
+!
+
+killAllRunningBackgroundProcesses
+
+    self backgroundProcesses do:[ : process |
+        self notifyChannel value:'kill ', process name.
+        process terminate.    
+    ].
+!
+
+makeExecutionResultProcessFor:aBlock withName:aString
+    | stream process appl nameString|
+
+    appl := self openCommandResultApplication.
+    stream := appl resultStream.
+    nameString := aString ? 'Execution Result'.
+    appl changeTabTo:nameString.
+    process := [ [aBlock value:stream] valueNowOrOnUnwindDo:[
+        self backgroundProcesses remove:process ifAbsent:[].
+        appl process value:nil.
+    ]] newProcess.
+    process priority:(Processor userBackgroundPriority).
+    process name:nameString.
+    self backgroundProcesses add:process.
+    appl process value:process.
+    process resume.
+! !
+
+!AbstractFileBrowser methodsFor:'change & update'!
+
+update:something with:aParameter from:changedObject
+
+    " do here all the things that have to be done for every part of the FileBrowserV2
+      and the things that have to be done if it runs standalone "
+
+    | newDirectories oldDirectories size|
+
+    changedObject == self currentFileNameHolder ifTrue:[
+        newDirectories := self getDirectoriesForFileList:(changedObject value).
+        oldDirectories := self currentDirectories value.
+        oldDirectories ~= newDirectories ifTrue:[
+            self currentDirectories value:newDirectories.
+            size := newDirectories size.
+            newDirectories notEmpty ifTrue:[
+                self enableDirectoryUp value:(((size == 1) and:[newDirectories first isRootDirectory not])).
+                newDirectories do:[: dir |
+                    self dirHistory addFile:dir.
+                ].
+                self enableForward value:self dirHistory canForward.
+                self enableBack value:self dirHistory canBack.
+            ]
+        ].
+        ^ self
+    ].
+    changedObject == self filterModel ifTrue:[
+        (self filterModel value = '') ifTrue:[
+            self filterModel value:'*'.
+        ].
+        ^ self
+    ].
+    super update:something with:aParameter from:changedObject
+! !
+
+!AbstractFileBrowser methodsFor:'clipboard'!
+
+canPaste
+
+    ^ self aspectFor:#canPaste ifAbsent:[ false asValue ].
+!
+
+clipboard
+
+    ^ self aspectFor:#clipboard ifAbsent:[Clipboard new]
+!
+
+copyFilesToClipBoard:colOfFiles
+    "defete current selected files/directories
+    "
+    self putInClipBoard:colOfFiles as:#copy.
+!
+
+cutFilesToClipBoard:colOfFiles
+    "defete current selected files/directories
+    "
+    self putInClipBoard:colOfFiles as:#cut.
+!
+
+emptyClipBoard
+
+    self clipboard files:nil.
+    self canPaste value:false.
+!
+
+putInClipBoard:colOfFiles as:aSymbol
+
+    | stream clp|
+
+    colOfFiles isEmpty ifTrue:[ ^ self].
+    clp := self clipboard.
+    clp files:nil.
+    clp method:aSymbol.
+    stream := WriteStream on:''.
+    stream nextPutAll:aSymbol asString.
+    stream nextPutAll:' <'.
+    stream nextPutAll:colOfFiles first asString.
+    colOfFiles size > 1 ifTrue:[
+        stream nextPutAll:' ...'.
+    ].
+    stream nextPutAll:'> to clipboard'.
+
+    self notifyChannel value:stream contents.
+    stream close.
+    clp files:colOfFiles.
+    self canPaste value:true.
+! !
+
+!AbstractFileBrowser methodsFor:'drag & drop'!
+
+canDropArchiv:dropedObjects for:filename 
+
+    (filename isDirectory 
+    and:[filename isWritable and:[dropedObjects notEmpty]])  ifTrue:[
+        ^ true
+    ].
+    ^ false
+!
+
+canDropFiles:dropedObjects for:filename 
+    | checkObject filenameDirString checkObjectString filenameDir|
+
+    dropedObjects isEmpty ifTrue:[^ false].
+    filenameDir := self getDirWithoutFileName:filename.
+    filenameDir isWritable not ifTrue:[^ false].
+    filenameDirString := filenameDir asString.
+    dropedObjects do:[:aObject | 
+        checkObject := aObject theObject.
+        checkObject isFilename not ifTrue:[^ false].
+        checkObject asFilename exists not ifTrue:[^ false].
+        checkObjectString := checkObject asString.
+        checkObject isDirectory ifTrue:[
+            (self fileName:filenameDirString startsWith:checkObjectString) ifTrue:[
+                " can not drop a directory in his parents "
+                ^ false
+            ]
+        ] ifFalse:[
+            (filenameDirString = checkObject directory asString 
+            or:[ filenameDirString = checkObject physicalPathName asFilename directory asString ]) ifTrue:[
+                " can not drop a file in same directory "
+                ^ false
+            ]
+        ]
+    ].
+    ^ true
+!
+
+doStartDrag:aDropSource in:aView
+    "set the cursors before starting the drag & drop operation
+    "
+    |hdl|
+
+
+    hdl := DragAndDropManager new.
+
+    hdl disabledCursor:self class DisabledCursorImage.
+    hdl enabledCursor:self class EnabledCursorImage.
+    hdl alienCursor:nil.
+
+    hdl startDragFrom:aView dropSource:aDropSource offset:#topLeft
+! !
+
+!AbstractFileBrowser methodsFor:'file operations'!
+
+copyFile:aSourceFile to:aDestFile
+    "copy to
+    "
+    |copy|
+
+    copy := FileOperation copy copyFile:aSourceFile to:aDestFile withOverWriteWarning:true copyFileIfSame:true.
+    copy result ifTrue:[
+        self notifyChannel value:('copy ', aSourceFile baseName, ' to:,', aDestFile baseName).
+    ] ifFalse:[
+        self notifyChannel value:copy errorString.
+    ].
+    ^ copy result
+!
+
+copyFiles:aColOfSourceFiles to:aDirectory 
+   "copy aColOfSourceFiles to aDirectory
+   "
+    |copy|
+
+    copy := FileOperation copy copyFiles:aColOfSourceFiles to:aDirectory.
+    copy result ifFalse:[
+        self notifyChannel value:copy errorString.
+    ].
+    self updateCurrentDirectory.
+    ^ copy colOfCopiedFiles
+!
+
+copyOrMoveDialog:aCol
+
+    | size stream dialog|
+
+    size := aCol size.
+    stream := WriteStream on:''.
+    stream nextPutAll:'copy or move file'.
+    size == 1 ifFalse:[
+        stream nextPutAll:'s'.
+    ].
+    stream nextPutAll:': '.
+    stream nextPutAll:aCol first baseName asString.
+    size == 1 ifFalse:[
+        stream nextPutAll:' ... '.
+        stream nextPutAll:aCol last baseName asString.
+    ].
+
+    dialog := OptionBox 
+                  request:stream contents 
+                  label:'move or copy'
+                  form:(WarningBox iconBitmap)
+                  buttonLabels:#('cancel' 'move' 'copy')
+                  values:#(#cancel #move #copy)
+                  default:#copy.
+    dialog isNil ifTrue:[dialog := #cancel].
+    ^ dialog.
+!
+
+copyOrMoveFiles:aColOfSourceFiles to:aDirectory 
+   "copy aColOfSourceFiles to aDirectory
+   "
+    |dialog|
+
+    dialog := self copyOrMoveDialog:aColOfSourceFiles.
+    dialog == #copy ifTrue:[
+        self copyFiles:aColOfSourceFiles to:aDirectory.
+        ^ self.
+    ].
+    dialog == #move ifTrue:[
+        self moveFiles:aColOfSourceFiles to:aDirectory.
+        ^ self.
+    ].
+!
+
+deleteFile:aFile
+    "delete current selected files/directories
+    "
+
+    ^ self deleteFiles:(OrderedCollection with:aFile).
+!
+
+deleteFiles:colOfFiles
+    "delete current selected files/directories
+    "
+    |delete|
+
+    delete := FileOperation delete deleteFiles:colOfFiles.
+    delete result ifFalse:[
+        self notifyChannel value:delete errorString.
+    ].
+    self updateCurrentDirectory.
+    ^ delete result.
+!
+
+moveFile:aSourceFile to:aDestFile
+    "defete current selected files/directories
+    "
+
+    |move|
+
+    move := FileOperation move moveFile:aSourceFile to:aDestFile.
+    move result ifTrue:[
+        self notifyChannel value:('move ', aSourceFile asString, ' to ', aDestFile asString).
+    ] ifFalse:[
+        self notifyChannel value:move errorString.
+    ].
+    self updateCurrentDirectory.
+    ^ move result
+!
+
+moveFiles:aColOfSourceFiles to:aDirectory 
+   "move aColOfSourceFiles to aDirectory
+   "
+    |move|
+
+    move := FileOperation move moveFiles:aColOfSourceFiles to:aDirectory.
+    move result ifFalse:[
+        self notifyChannel value:move errorString.
+    ].
+    self updateCurrentDirectory.
+    ^ move colOfMovedFiles
+!
+
+newDirectory
+    "ask for and create a new directory"
+
+    | directories directory create newFile|
+
+    directories := self currentDirectories value.
+    (directories size ~= 1) ifTrue:[^ self].
+    directory := directories first.
+    create := FileOperation create createDirectoryIn:directory.
+    create result ifFalse:[ ^ self].
+    newFile := create createdFile.
+    newFile notNil ifTrue:[
+        self updateAndSelect:(OrderedCollection with:newFile).
+    ]
+!
+
+newFile
+    "ask for and create a new file"
+
+    | curFile directories directory create file|
+
+    directories := self currentDirectories value.
+    (directories size ~= 1) ifTrue:[^ self].
+    directory := directories first.
+    curFile := self getFirstFileFromSelection.
+    curFile notNil ifTrue:[
+        file := curFile.
+    ] ifFalse:[
+        file := directory.
+    ].
+    create := FileOperation create createFileIn:file.
+    create result ifFalse:[ ^ self].
+    self updateAndSelect:(OrderedCollection with:(create createdFile)).
+!
+
+newHardLink
+    "ask for and create a hard link (unix only)"
+
+    self newLink:false.
+!
+
+newLink:symbolic
+
+    "ask for and create a symbolic if symbolic is true otherwise a hard link (unix only)"
+
+    | sel create createdFile|
+
+    sel := self currentFileNameHolder value.
+    (sel size ~= 1) ifTrue:[^ self].
+    symbolic ifTrue:[
+        create := FileOperation create createSoftLinkIn:(sel first).
+    ] ifFalse:[
+        create := FileOperation create createHardLinkIn:(sel first).
+    ].
+    create result ifFalse:[ ^ self].
+    createdFile := create createdFile.
+    createdFile notNil ifTrue:[
+        self updateAndSelect:(OrderedCollection with:createdFile).
+    ].
+!
+
+newSoftLink
+    "ask for and create a soft link (unix only)"
+
+    self newLink:true.
+!
+
+pasteFiles
+    "defete current selected files/directories
+    "
+    | buffer destination files directories copiedFiles|
+
+    files := self clipboard files.
+    (files isNil or:[files isEmpty]) ifTrue:[ ^ self ].
+    buffer := self clipboard copy.
+    directories := self getDirectoriesFromSelection.
+    directories isEmpty ifTrue:[
+        |box dirStringCol|
+        dirStringCol := directories collect:[:aDir| aDir asString].
+        box := ListSelectionBox new.
+        box title:'In which directory you want to paste ?'.
+        box list:dirStringCol.
+        box okAction:[:sel | destination := sel asFilename].
+        box showAtPointer
+    ] ifFalse:[
+        destination := directories first.
+    ].
+    copiedFiles := self copyFiles:(buffer files) to:destination.
+    
+    (self clipboard method == #cut) ifTrue:[
+        self deleteFiles:copiedFiles.
+    ] 
+!
+
+renameFile:aFile 
+    "rename the selected file(s)"
+
+    ^ self renameFiles:(OrderedCollection with:aFile).
+!
+
+renameFile:filename to:newFileString  update:aBoolean
+    "rename filename to newFileString"
+
+    |rename|
+
+    rename := FileOperation rename renameFile:filename to:newFileString.
+    rename result ifTrue:[
+        aBoolean ifTrue:[
+            self updateAndSelect:(rename renamedFiles).
+        ].
+    ] ifFalse:[
+        self notifyChannel value:rename errorString.
+    ].
+    ^ rename result
+!
+
+renameFiles:aColOfFiles 
+    "rename the selected file(s)"
+
+    |rename|
+
+    rename := FileOperation rename renameFiles:aColOfFiles.
+    rename result ifFalse:[
+        self notifyChannel value:rename errorString
+    ] ifTrue:[
+        self updateAndSelect:(rename renamedFiles)
+    ].
+    ^ rename result
+!
+
+renameSelection
+    "rename the selected file(s)"
+
+    |rename|
+
+    rename := FileOperation rename renameFiles:self currentFileNameHolder value.
+    rename result ifFalse:[
+        self notifyChannel value:rename errorString
+    ] ifTrue:[
+        self updateAndSelect:(rename renamedFiles)
+    ].
+    ^ rename result
+! !
+
+!AbstractFileBrowser methodsFor:'font encoding'!
+
+fileEncoding
+    "open a dialog to allow change of the files character encoding.
+     Files are converted to internal encoding when read, and converted back
+     to this encoding when saved.
+     The default encoding is nil, which means that files are already in
+     the internal encoding (which is iso8859).
+     Notice: currently, not too many encodings are supported by the system."
+
+    |dialog list descr encodings encodingNames idx|
+
+    list := SelectionInList new.
+
+    descr := CharacterArray supportedExternalEncodings.
+    encodings := descr at:2.
+    encodingNames := descr at:1.
+
+    list list:encodingNames.
+    list selectionIndex:(encodings indexOf:(self fileEncodingHolder value) ifAbsent:1).
+    dialog := Dialog new.
+
+    dialog addTextLabel:('Specify the files encoding.\\The default (a 1-to-1 encoding) works for 7bit ascii\and iso8859 (= ANSI) encoded text files.\') withCRs.
+    dialog addVerticalSpace.
+    dialog addListBoxOn:list withNumberOfLines:5.
+
+    dialog addAbortAndOkButtons.
+    dialog open.
+
+    dialog accepted ifTrue:[
+        idx := list selectionIndex.
+        self fileEncodingHolder value:(encodings at:idx).
+"/        subView externalEncoding:fileEncoding.
+
+        self validateFontEncodingFor:(encodings at:idx) ask:true.
+    ].
+!
+
+fileEncodingHolder
+    "return/create the 'fileEncodingModel' value holder (automatically generated)"
+
+    ^ self aspectFor:#fileEncodingHolder ifAbsent:[ValueHolder new]
+!
+
+preferredFontEncodingFor:fileEncoding
+    "given a file encoding, return corresponding preferred fontEncoding
+     match pattern"
+
+    |fe|
+
+    fe := MIMETypes fontForCharset:fileEncoding.
+    fe notNil ifTrue:[^ fe].
+    ^ 'iso8859*'
+!
+
+validateFontEncodingFor:newEncoding ask:ask
+    "if required, query user if he/she wants to change to another font,
+     which is able to display text encoded as specified by newEncoding"
+
+    |fontsEncoding msg filter f defaultFont pref|
+
+"/ PENK    fontsEncoding := subView font encoding.
+
+    pref := self preferredFontEncodingFor:newEncoding.
+
+    (pref match:fontsEncoding) ifTrue:[
+        ^ self
+    ].
+    "/ stupid ...
+    pref = 'ascii*' ifTrue:[
+        (fontsEncoding match:'iso8859*') ifTrue:[
+            ^ self
+        ]
+    ].
+
+    filter := [:f | |coding|
+                    (coding := f encoding) notNil 
+                    and:[pref match:coding]].
+
+    defaultFont := TextView defaultFont onDevice:device.
+    (pref match:(defaultFont encoding)) ifFalse:[
+        defaultFont := nil.
+    ].
+
+    defaultFont isNil ifTrue:[
+        (pref = 'ascii*'
+        or:[pref = 'iso8859*']) ifTrue:[
+            defaultFont := FontDescription family:'courier' face:'medium' style:'roman' size:12
+        ]
+    ].
+
+    defaultFont isNil ifTrue:[
+        defaultFont := device 
+                            listOfAvailableFonts 
+                                detect:[:f | filter value:f]
+                                ifNone:nil.
+        defaultFont isNil ifTrue:[
+
+            "/ flush list, and refetch font list
+            "/ (in case someone just changed the font path ...)
+
+            device flushListOfAvailableFonts.
+            defaultFont := device 
+                                listOfAvailableFonts 
+                                    detect:[:f | filter value:f]
+                                    ifNone:nil.
+        ].
+
+        defaultFont isNil ifTrue:[
+            Dialog warn:'your display does not seem to provide any ' , newEncoding , '-encoded font.'.
+            ^ self.
+        ]
+    ].
+
+    msg := 'switch to a %1 encoded font ?'.
+    (ask not or:[self confirm:(resources string:msg with:pref) withCRs])
+    ifTrue:[
+        self withWaitCursorDo:[
+            f := FontPanel 
+                fontFromUserInitial:defaultFont
+                              title:(resources string:'font selection')
+                             filter:filter.
+            f notNil ifTrue:[
+"/ PENK               subView font:f
+            ]
+        ]
+    ]
+! !
+
+!AbstractFileBrowser methodsFor:'menu'!
+
+menuDirHistory:backOrForward
+    "initialize the directory menu
+    "
+    <resource: #programMenu >
+
+    |menu histCopy index text removeItem directories dir|
+
+    menu := Menu new.
+    menu receiver:self.
+
+    directories := self getDirectoriesFromSelection.
+    directories isEmpty ifTrue:[^ nil].
+
+    dir := directories first.
+    self dirHistory isEmpty ifTrue:[^ nil].
+    index := self dirHistory indexOf:dir.
+    index = 0 ifTrue:[^ nil].
+    text := LabelAndIcon icon:(self class clearHistoryIcon) string:'Clear History'.
+    backOrForward == #back ifTrue:[
+        histCopy := self dirHistory copyTo:index - 1.
+        removeItem := MenuItem label:text value:[
+            self dirHistory removeBack.
+            self enableBack value:self dirHistory canBack.
+        ].
+    ] ifFalse:[
+        histCopy := self dirHistory copyFrom:index + 1.
+        removeItem := MenuItem label:text value:[
+            self dirHistory removeForward.
+            self enableForward value:self dirHistory canForward.
+        ].
+    ].
+    histCopy do:[:aFile| 
+        menu addItem:(MenuItem label:aFile asString value:[
+            self dirHistory setIndexTo:aFile.
+            self currentFileNameHolder value:(OrderedCollection with:aFile).
+        ]).
+    ].
+    menu addItem:(MenuItem label:'-').
+    menu addItem:removeItem.
+    ^ menu
+!
+
+menuDirHistoryBack
+    "initialize the directory menu
+    "
+    <resource: #programMenu >
+
+    ^ self menuDirHistory:#back.
+!
+
+menuDirHistoryForward
+    "initialize the directory menu
+    "
+    <resource: #programMenu >
+
+    ^ self menuDirHistory:#forward.
+! !
+
+!AbstractFileBrowser methodsFor:'menu access'!
+
+sortMenu
+
+    ^ self application:#DirectoryContentsBrowser do:#sortMenu.
+!
+
+viewFileBrowserMenu
+
+    ^ self application:#DirectoryContentsBrowser do:#viewBrowserMenu.
+! !
+
+!AbstractFileBrowser methodsFor:'menu actions cvs'!
+
+cvsAddAndCommit
+
+    self cvsAddAndCommit:true.
+!
+
+cvsAddAndCommit:withCommit
+
+    |sel log cmd dir directories executionBlock nameString block|
+
+    log := Dialog
+        requestText:(resources string:'enter initial log message')
+        lines:10
+        columns:70
+        initialAnswer:nil.
+
+    sel := self getFilesFromSelection.
+    executionBlock := [ : stream |
+        log notNil ifTrue:[
+            sel size > 0 ifTrue:[
+                sel do:[:fn |
+                    dir := self getDirWithoutFileName:fn.
+                    cmd := ('cvs add -m ''' , log , ''' ' , fn baseName).
+                    block := self getExecutionBlockForCommand:cmd inDirectory:dir.
+                    block value:stream.
+                ]
+            ] ifFalse:[
+                directories := self currentDirectories value.
+                directories do:[:dir |
+                    cmd := ('cvs add -m ''' , log , ''' ' , dir baseName).
+                    block := self getExecutionBlockForCommand:cmd inDirectory:dir.
+                    block value:stream.
+                ]
+            ].
+            withCommit ifTrue:[
+                cmd := ('cvs commit -l -m ''' , log , '''').
+                block := self getExecutionBlockForCommand:cmd.
+                block value:stream.
+            ]
+        ]
+    ].
+    nameString := 'Command> add and commit'.
+    self makeExecutionResultProcessFor:executionBlock withName:nameString.
+!
+
+cvsCommit
+
+    |nSel log msg cmd selectedFiles|
+
+    selectedFiles:= self getFilesFromSelection.
+    nSel := selectedFiles size.
+
+    nSel == 1 ifTrue:[
+        msg := resources string:'enter log message for checkIn of ''%1''' with:(selectedFiles first baseName)
+    ] ifFalse:[
+        nSel > 1 ifTrue:[
+            msg := resources string:'enter log message for %1 files to checkIn' with:nSel printString
+        ] ifFalse:[
+            msg := resources string:'enter log message for checkIn'
+        ]
+    ].
+
+    log := Dialog
+        requestText:msg
+        lines:10
+        columns:70
+        initialAnswer:nil.
+
+    log notNil ifTrue:[
+        nSel > 0 ifTrue:[
+            selectedFiles do:[:fn |
+                cmd := ('cvs commit -m ''' , log , ''' ' , fn baseName).
+                self executeCommand:cmd.
+            ]
+        ] ifFalse:[
+            cmd := ('cvs commit -l -m ''' , log , '''').
+            self executeCommand:cmd.
+        ].
+    ]
+!
+
+cvsRemoveAndRemoveFromCVS:filesToRemove
+    "remove the selected file(s) and their CVS containers - no questions asked"
+
+    |msg toRemove updateRunning cmd executionBlock nameString|
+
+    updateRunning := self backgroundProcesses value notEmpty.
+    self killAllRunningBackgroundProcesses.
+    toRemove := OrderedCollection new.
+
+    executionBlock := [ : stream |
+        | block |
+        filesToRemove do:[:fileName |
+            OperatingSystem accessDeniedErrorSignal handle:[:ex|
+                "was not able to remove it"
+                | lastError |
+                lastError := OperatingSystem lastErrorString.
+                msg := (resources string:'cannot remove ''%1'' !!' with:fileName).
+                lastError isNil ifFalse:[
+                    msg := msg , '\\(' , lastError , ')'
+                ].
+                Dialog warn:msg withCRs
+            ] do:[
+                |answer contents|
+
+                (fileName isSymbolicLink not) ifTrue:[
+                    fileName remove.
+                    cmd := ('cvs remove -f ' , fileName baseName).
+                    block := self getExecutionBlockForCommand:cmd.
+                    block value:stream.
+                ]
+            ].
+        ].
+
+        cmd := ('cvs commit -m ''removed via FileBrowser''').
+        block := self getExecutionBlockForCommand:cmd. 
+        block value:stream.
+    ].
+    nameString := 'Command> remove and commit ', filesToRemove first baseName.
+    filesToRemove size > 1 ifTrue:[
+        nameString := nameString, ' ...'.
+    ].
+    self makeExecutionResultProcessFor:executionBlock withName:nameString.
+!
+
+cvsRemoveFileAndCVSContainer
+
+    |sel question aswer|
+
+    sel := self getFilesFromSelection.
+
+    sel size > 0 ifTrue:[
+        sel size > 1 ifTrue:[
+            question := resources string:'Remove %1 selected files and their CVS containers ?' with:(sel size)
+        ] ifFalse:[
+            question := resources string:'Remove ''%1'' and its CVS container ?' with:(sel first baseName allBold)
+        ].
+
+        aswer := Dialog 
+                confirm:question withCRs
+                yesLabel:(resources at:'Remove')
+                noLabel:(resources at:'Cancel').
+        aswer ifTrue:[
+            self withCursor:(Cursor wait) do:[
+                self cvsRemoveAndRemoveFromCVS:sel
+            ]
+        ]
+    ]
+!
+
+cvsUpdateAll
+
+    | cmd |
+
+    cmd := 'cvs upd -l'.
+    self executeCommand:cmd.
+!
+
+cvsUpdateAllRecursive
+
+    | cmd |
+
+    cmd := 'cvs upd -d'.
+    self executeCommand:cmd.
+!
+
+cvsUpdateSelection
+
+    | selectedFiles stream|
+
+
+    selectedFiles:= self getFilesFromSelection.
+    stream := WriteStream on:''.
+    stream nextPutAll:'cvs upd '.
+    selectedFiles do:[: file |
+        stream nextPutAll:file baseName.
+        stream space.
+    ].
+    self executeCommand:stream contents.
+    stream close.
+! !
+
+!AbstractFileBrowser methodsFor:'menu actions edit'!
+
+copyInDirContentsBrowser
+
+    ^ self application:#DirectoryContentsBrowser do:#doCopy.
+!
+
+cutInDirContentsBrowser
+
+    ^ self application:#DirectoryContentsBrowser do:#doCut.
+!
+
+deleteInDirContentsBrowser
+
+    ^ self application:#DirectoryContentsBrowser do:#doDelete.
+! !
+
+!AbstractFileBrowser methodsFor:'menu actions tools'!
+
+createProjectAndOpenProjectBrowser
+    |nm f s directory|
+
+    self currentFilesAreInSameDirectory ifFalse:[^ self].
+    directory := self currentDirectories value first.
+    nm := directory baseName.
+    f := (directory  construct:nm) withSuffix:'prj'.
+    f exists ifTrue:[
+        Dialog warn:'A file named ' , f baseName , ' already exists.'.
+        ^ self.
+    ].
+    s := f writeStream.
+    s nextPutAll:'
+name            ''' , nm , '''
+type            #classLibrary
+package         #''private:' , nm , '''
+prerequisites   nil
+
+classes      #( )
+'.
+    s close.
+    ProjectBrowser openOnFile:f.
+!
+
+fileFileIn
+    "fileIn the selected file(s)"
+
+    self fileFileInLazy:false 
+!
+
+fileFileInLazy
+    "fileIn the selected file(s). Do a quick load (no compilation)"
+
+    self fileFileInLazy:true 
+!
+
+fileFileInLazy:lazy
+    "fileIn the selected file(s)"
+
+    | selectedFiles|
+
+    selectedFiles:= self getFilesFromSelection.
+    selectedFiles do:[:fileName |
+        self singleFileFileIn:fileName lazy:lazy
+    ].
+!
+
+fileFileInToNameSpace
+    "fileIn the selected file(s)<into a nameSpace"
+
+    |ns listOfKnownNameSpaces|
+
+    listOfKnownNameSpaces := Set new.
+    NameSpace 
+        allNamespaces 
+            do:[:eachNameSpace | 
+                listOfKnownNameSpaces add:eachNameSpace name
+            ].
+    listOfKnownNameSpaces := listOfKnownNameSpaces asOrderedCollection sort.
+
+    ns := Dialog 
+                request:'During fileIn, new classes are created in nameSpace:'
+                initialAnswer:(LastEnforcedNameSpace ? Class nameSpaceQuerySignal query name)
+                list:listOfKnownNameSpaces.
+    ns isEmptyOrNil ifTrue:[^ self].
+
+    LastEnforcedNameSpace := ns.
+    ns := NameSpace name:ns.
+
+    Class nameSpaceQuerySignal 
+        answer:ns
+        do:[ self fileFileInLazy:false ] 
+!
+
+fileFindAllDuplicates
+    "scan directory and all subdirs for duplicate files"
+
+    |fileNames dir infoDir filesBySize
+     result info dirPrefix myName stream textBox maxLength directories|
+
+
+    self withWaitCursorDo:[
+        result := Dictionary new.
+        myName := self class name asString.
+        directories := self getDirectoriesFromSelection.
+        directories isEmpty ifTrue:[^ self].
+        
+        dir := directories first.
+"/        self label: myName, '- gathering file names ...'.
+        fileNames := dir recursiveDirectoryContents.
+        fileNames := fileNames collect:[:fn | dir construct:fn].
+        fileNames := fileNames select:[:fn | fn isDirectory not].
+
+"/        self label:myName , '- gathering sizes ...'.
+        infoDir := Dictionary new.
+        fileNames do:[:fn |
+            infoDir at:fn put:(fn fileSize)
+        ].
+
+        "/ for each, get the files size.
+        "/ in a first pass, look for files of the same size and
+        "/ compare them ...
+
+"/        self label:myName , '- preselect possible duplicates ...'.
+        filesBySize := Dictionary new.
+        infoDir keysAndValuesDo:[:fn :sz |
+            |entry|
+
+            entry := filesBySize at:sz ifAbsentPut:[Set new].
+            entry add:fn.
+        ].
+
+        "/ any of same size ?
+
+"/        self label:myName , '- checking for duplicates ...'.
+        filesBySize do:[:entry |
+            |files|
+
+            entry size > 1 ifTrue:[
+                files := entry asArray.
+                1 to:files size-1 do:[:idx1 |
+                    idx1+1 to:files size do:[:idx2 |
+                        |fn1 fn2|
+
+                        fn1 := files at:idx1.
+                        fn2 := files at:idx2.
+
+"/                        self label:myName , '- checking ' , fn1 baseName , ' vs. ' , fn2 baseName , ' ...'.
+                        (result at:fn2 ifAbsent:nil) ~= fn1 ifTrue:[
+                            "/ compare the files
+                            (fn1 sameContentsAs:fn2) ifTrue:[
+"/                                Transcript show:'Same: '; show:fn1 baseName; show:' and '; showCR:fn2 baseName.
+                                result at:fn1 put:fn2.
+                            ]
+                        ]
+                    ]
+                ]
+            ]
+        ].
+
+"/        self label:myName , '- sorting ...'.
+        dirPrefix := dir pathName.
+        result := result associations.
+        result := result collect:[:assoc |
+                                        |f1 f2|
+
+                                        f1 := assoc key name.
+                                        f2 := assoc value name.
+                                        (f1 startsWith:dirPrefix) ifTrue:[
+                                            f1 := f1 copyFrom:dirPrefix size + 2.
+                                        ].
+                                        (f2 startsWith:dirPrefix) ifTrue:[
+                                            f2 := f2 copyFrom:dirPrefix size + 2.
+                                        ].
+                                        f1 < f2 ifTrue:[
+                                            f2 -> f1
+                                        ] ifFalse:[
+                                            f1 -> f2
+                                        ]
+                                ].
+        result sort:[:f1 :f2 | f2 value < f1 value].
+
+        info := OrderedCollection new.
+        result do:[:assoc |
+            info add:(assoc key , ' same as ' , assoc value)
+        ].
+        info isEmpty ifTrue:[
+            info := 'No duplicate files found.'
+        ].
+    ].
+
+    stream := WriteStream on:''.
+    info do:[:el|
+        stream nextPutAll:el.
+        stream cr.
+    ].
+    textBox := TextBox new.
+    textBox initialText:(stream contents).
+    textBox title:'File dublicates in directory: ', dir asString.
+    textBox readOnly:true.
+    textBox noCancel.
+    textBox label:'Dublicates in ', dir asString.
+    maxLength := 10.
+    info do:[: el |
+        maxLength := maxLength max:(el size).
+    ].
+    textBox extent:((maxLength * 5)@(info size * 20)); sizeFixed:false.
+    textBox showAtPointer.
+    stream close.
+"/    subView contents:info.
+"/    self label:myName.
+!
+
+fileFindDuplicates
+    "scan directory for duplicate files"
+
+    |fileNames dir infoDir filesBySize
+     result info stream textBox maxLength directories allFiles titleStream size|
+
+"/    (self askIfModified:'contents has not been saved.\\Modifications will be lost when you proceed.'
+"/              yesButton:'proceed') ifFalse:[^ self].
+
+    self withWaitCursorDo:[
+        result := Dictionary new.
+
+        directories := self getDirectoriesFromSelection.
+        directories isEmpty ifTrue:[^ self].
+
+        allFiles := OrderedCollection new.
+        directories do:[ : dir|
+            fileNames := dir directoryContents.
+            fileNames := fileNames collect:[:fn | dir construct:fn].
+            fileNames := fileNames select:[:fn | fn isDirectory not].
+            allFiles addAll:fileNames.
+        ].
+
+        infoDir := Dictionary new.
+        allFiles do:[:fn |
+            infoDir at:fn put:(fn info)
+        ].
+
+        "/ for each, get the files size.
+        "/ in a first pass, look for files of the same size and
+        "/ compare them ...
+
+        filesBySize := Dictionary new.
+        infoDir keysAndValuesDo:[:fn :info |
+            |sz entry|
+
+            sz := info size.
+            entry := filesBySize at:sz ifAbsentPut:[Set new].
+            entry add:fn.
+        ].
+
+        "/ any of same size ?
+
+        filesBySize do:[:entry |
+            |files|
+
+            entry size > 1 ifTrue:[
+                files := entry asArray.
+                1 to:files size-1 do:[:idx1 |
+                    idx1+1 to:files size do:[:idx2 |
+                        |fn1 fn2|
+
+                        fn1 := files at:idx1.
+                        fn2 := files at:idx2.
+
+                        (result at:fn2 ifAbsent:nil) ~= fn1 ifTrue:[
+                            "/ compare the files
+                            (fn1 sameContentsAs:fn2) ifTrue:[
+"/                                Transcript show:'Same: '; show:fn1 baseName; show:' and '; showCR:fn2 baseName.
+                                result at:fn1 put:fn2.
+                            ]
+                        ]
+                    ]
+                ]
+            ]
+        ].
+
+        result := result associations.
+        result := result collect:[:assoc |
+                                        |f1 f2|
+
+                                        f1 := assoc key asString.
+                                        f2 := assoc value asString.
+                                        f1 < f2 ifTrue:[
+                                            f2 -> f1
+                                        ] ifFalse:[
+                                            f1 -> f2
+                                        ]
+                                ].
+        result sort:[:f1 :f2 | f2 value < f1 value].
+
+        info := OrderedCollection new.
+        size := self getBestDirectory asString size.
+        result do:[:assoc |
+            |fn1 fn2|
+
+            fn1 := assoc key.
+            fn2 := assoc value.
+            size > 1 ifTrue:[
+                fn1 := ('..', (fn1 copyFrom:(size + 1))).
+                fn2 := ('..', (fn2 copyFrom:(size + 1))).
+            ].
+            (fn1 includes:Character space) ifTrue:[
+                fn1 := '"' , fn1 , '"'
+            ].
+            (fn2 includes:Character space) ifTrue:[
+                fn2 := '"' , fn2 , '"'
+            ].
+            info add:(fn1 , ' same as ' , fn2)
+        ].
+        info isEmpty ifTrue:[
+            info add:'No duplicate files found.'
+        ].
+    ].
+    stream := WriteStream on:''.
+    info do:[:el|
+        stream nextPutAll:el.
+        stream cr.
+    ].
+    titleStream := WriteStream on:''.
+    titleStream nextPutAll:'File dublicates in director'.
+    directories size == 1 ifTrue:[
+        titleStream nextPutAll:'y: ', directories first asString.
+    ] ifFalse:[
+        titleStream nextPutAll:'ies: '.
+        titleStream cr.
+        directories do:[:dir|
+            size > 1 ifTrue:[
+                titleStream nextPutAll:'..'.
+                titleStream nextPutAll:((dir asString) copyFrom:(size + 1)).
+            ] ifFalse:[
+                titleStream nextPutAll:(dir asString).
+            ].
+            titleStream cr.
+        ]
+    ].
+    
+    textBox := TextBox new.
+    textBox initialText:(stream contents).
+    textBox title:(titleStream contents).
+    textBox readOnly:true.
+    textBox noCancel.
+    textBox label:'Dublicates in ', dir asString.
+    maxLength := 10.
+    info do:[: el |
+        maxLength := maxLength max:(el size).
+    ].
+    textBox extent:((maxLength * 5)@(info size * 10)); sizeFixed:false.
+    textBox showAtPointer.
+    titleStream close.
+    stream close.
+!
+
+fileFindFile
+    |filename files|
+
+    files := self currentFileNameHolder value.
+    files notEmpty ifTrue:[
+        filename := files first.
+    ] ifFalse:[
+        filename := (Filename homeDirectory).
+    ].
+    FindFileApplication openOnFileName:filename.
+!
+
+installAllAsAutoloaded
+    "install all classes found here as autoloaded classes"
+
+    self allItemsOfCurrentDirectory do:[:fileItem |
+        (fileItem hasMimeType and:[fileItem mimeType isSmalltalkSource]) ifTrue:[
+            self installAsAutoloaded:(fileItem fileName).
+        ]
+    ].
+!
+
+installAsAutoloaded:aFilename
+    "install aFilename as autoloaded class"
+
+    |chunks s|
+
+    chunks := ChangeSet fromStream:(s := aFilename asFilename readStream). s close.
+    chunks 
+        select:[:eachChunk | eachChunk isClassDefinitionChange]
+        thenDo:[:eachClassChunk | eachClassChunk installAsAutoloadedClassIfNotPrivate].
+!
+
+loadImageAndPerform:aSelectorOrBlock
+
+    |img path files|
+
+    files := self getFilesFromSelection.
+    files isEmpty ifTrue:[ ^ self].
+    files do:[:fileName |
+        path := fileName.
+        path isDirectory ifFalse:[
+            img := Image fromFile:(path pathName).
+            img notNil ifTrue:[
+                aSelectorOrBlock isSymbol ifTrue:[
+                    img perform:aSelectorOrBlock
+                ] ifFalse:[
+                    aSelectorOrBlock value:img
+                ]
+            ] ifFalse:[
+                Dialog warn:'unknown format: ' , fileName asString
+            ]
+        ]
+    ].
+!
+
+openASN1Browser
+
+    self openTool:OSI::ASN1Browser 
+!
+
+openAppletViewer
+    |numItems files|
+
+    files := self getFilesFromSelection.
+    (numItems := files size) > 2 ifTrue:[
+        (self 
+            confirm:(resources string:'open for each of the %1 items ?' 
+                                 with:numItems)) ifFalse:[^ self].
+    ].
+
+    Java startupJavaSystem.
+"/    Java markAllClassesUninitialized.
+"/    Java initAllStaticFields.
+"/    Java initAllClasses.
+
+    files do:[:fileName |
+        |p path|
+
+        path := fileName.
+        path isDirectory ifFalse:[
+            p := Java 
+                    javaProcessForMainOf:(Java classForName:'sun.applet.AppletViewer')
+                    argumentString:path pathName.
+            p resume.
+        ]
+    ].
+!
+
+openCBrowser
+
+    |directories|
+
+    directories := self getDirectoriesFromSelection.
+    directories isEmpty ifTrue:[ ^ self].
+    self withWaitCursorDo:[
+        CBrowser::Browser openIn:directories first.
+    ]
+!
+
+openChangesBrowser
+    "open a change browser on the selected file(s)"
+
+    self openTool:(UserPreferences current changesBrowserClass)
+!
+
+openDiffView
+    "open a diff-view"
+
+    | name1 name2 text1 text2 f d err nm l1 files title|
+
+    files := self getFilesFromSelection.
+    files isEmpty ifTrue:[
+        Dialog warn:'you have to select a file first'.
+        ^ self.
+    ].
+    (files size == 2) ifTrue:[
+        name1 := files last.
+        name2 := files first.
+    ] ifFalse:[
+        LastFileDiffFile notNil ifTrue:[
+"/            f := self currentDirectory value asFilename construct:(LastFileDiffFile baseName).
+            (LastFileDiffFile exists
+            and:[LastFileDiffFile isReadable]) ifTrue:[
+                name1 := f.
+            ]
+        ].
+        name2 := files first.
+        title := 'show difference between ', name2 baseName.
+        name1 := FileSelectionBox requestFileName:title default:(name1 baseName) fromDirectory:(name2 asFilename pathName).
+    ].
+
+    (name1 isNil or:[name1 asString isEmpty]) ifTrue:[
+        text1 := self getAllFilesAsStringCollection asStringCollection withTabs.
+        text1 := text1 collect:[:l | l isNil ifTrue:[' '] ifFalse:[l]].
+        name1 := nil.
+        l1 := 'browser contents'
+    ] ifFalse:[
+        LastFileDiffFile := name1.
+        name1 isReadable ifFalse:[
+            nm := name1.
+            name1 exists ifFalse:[
+                err := '%1 does not exist'.
+            ] ifTrue:[
+                err := '%1 is not readable'
+            ].
+        ].
+        l1 := name1 pathName
+    ].
+
+    err isNil ifTrue:[
+        name2 isReadable ifFalse:[
+            nm := name2.
+            name2 exists ifFalse:[
+                err := '%1 does not exist'.
+            ] ifTrue:[
+                err := '%1 is not readable'
+            ].
+        ].
+    ].
+    err notNil ifTrue:[
+        Dialog warn:(resources string:err with:nm pathName).
+        ^ self
+    ].
+
+    self withWaitCursorDo:[
+        name1 notNil ifTrue:[
+            text1 := name1 contents.
+        ].
+        text2 := name2 contents.
+        text1 = text2 ifTrue:[
+            self information:'same contents'
+        ] ifFalse:[
+            d := DiffTextView 
+                    openOn:text1 label:l1
+                    and:text2 label:name2 pathName.
+            d label:'file differences'.
+        ]
+    ]
+!
+
+openEditor
+    self openTool:EditTextView
+!
+
+openHTMLReader
+
+    self openTool:HTMLDocumentView ignoreDirectories:false
+!
+
+openImageEditor
+
+    [self loadImageAndPerform:#edit] fork
+!
+
+openImageInspector
+    [self loadImageAndPerform:#inspect] fork
+!
+
+openImagePreview
+
+    [self loadImageAndPerform:[:img |
+                                |i top viewer|
+
+                                top := StandardSystemView new.
+
+                                viewer := ImageView origin:0.0@0.0 corner:1.0@1.0 in:top.
+                                i := img.
+                                top extent:200@200.
+                                top label:(img fileName asFilename directoryName asFilename baseName , '/' , img fileName asFilename baseName).
+                                top openAndWait.
+
+                                (i width > 200 or:[i height > 200]) ifTrue:[
+                                    i := i magnifiedPreservingRatioTo:200@200.
+                                ].
+                                viewer image:i.
+                              ].
+    ] fork
+!
+
+openMP3Player
+    |file|
+
+    file := self getFilesFromSelection.
+    (file isEmpty) ifTrue:[
+        ^ self.
+    ].
+    file := file first.
+    (MP3PlayerApplication ? SaugFix::MP3PlayerApplication) playSong:file.
+!
+
+openSlideShow
+
+    |directories dir|
+
+    directories := self getDirectoriesFromSelection.
+    directories isEmpty ifTrue:[^ self].
+
+    dir := directories first.
+    CodingExamples_GUI::SlideShow openIn:dir.
+!
+
+openSnapshotImageBrowser
+    ^ self openTool:SystemBrowser with:#openOnSnapShotImage: ignoreDirectories:true
+!
+
+openTerminal
+
+    |directories dir|
+
+    directories := self getDirectoriesFromSelection.
+    directories isEmpty ifTrue:[
+        dir := Filename homeDirectory.
+    ] ifFalse:[
+        dir := directories first.
+    ].
+
+    VT100TerminalView openShellIn:dir.
+!
+
+openTool:aToolClass
+    "open a tool on the selected file(s)"
+
+    ^ self openTool:aToolClass ignoreDirectories:true
+!
+
+openTool:aToolClass ignoreDirectories:ignoreDirs
+    "open a tool on the selected file(s)"
+
+    ^ self
+        openTool:aToolClass 
+        with:#openOn: 
+        ignoreDirectories:ignoreDirs
+!
+
+openTool:aToolClass with:aSelector ignoreDirectories:ignoreDirs
+    "open a tool on the selected file(s)"
+
+    |numItems path tool files|
+
+    aToolClass isNil ifTrue:[
+        Dialog warn:'Sorry, that tool seems to be not available'.
+        ^ nil.
+    ].
+    files := self getFilesFromSelection.
+    
+    (numItems := files size) > 2 ifTrue:[
+        (self 
+            confirm:(resources string:'open for each of the %1 items ?' 
+                                 with:numItems)) ifFalse:[^ self].
+    ].
+
+    self withWaitCursorDo:[
+        files do:[:fileName |
+            (ignoreDirs not or:[fileName isDirectory not]) ifTrue:[
+                fileName isAbsolute ifTrue:[
+                    path := fileName getName.
+                ] ifFalse:[
+                    path := fileName pathName.
+                ].
+                tool := aToolClass perform:aSelector with:path.
+            ]
+        ].
+    ].
+    ^ tool
+!
+
+openZipTool
+    |zipTool directories dir|
+
+    (zipTool := self openTool:ZipTool) notNil ifTrue:[
+        directories := self getDirectoriesFromSelection.
+        directories isEmpty ifTrue:[
+            dir := directories first.
+        ] ifFalse:[
+            dir := Filename homeDirectory.
+        ].
+
+        zipTool initialExtractDirectory:dir.
+    ].
+!
+
+readAbbrevFile
+    "read the abbrev file and install classes found there as autoloaded classes"
+
+    | directories dir|
+
+    directories := self getDirectoriesFromSelection.
+    directories isEmpty ifTrue:[^ self].
+
+    dir := directories first.
+    Smalltalk installAutoloadedClassesFrom:(dir construct:'abbrev.stc').
+!
+
+singleFileFileIn:fileName lazy:lazy
+    "fileIn the selected file(s)"
+
+    |aStream wasLazy|
+
+    fileName type == #regular ifTrue:[
+
+        (ObjectFileLoader notNil
+        and:[ObjectFileLoader hasValidBinaryExtension:fileName]) ifTrue:[
+            AbortOperationRequest catch:[
+                |p|
+
+                "/
+                "/ look if already loaded ...  then unload first
+                "/
+                p := fileName pathName.
+                (ObjectFileLoader loadedObjectFiles includes:p) ifTrue:[
+                    (Dialog confirm:(resources 
+                                        string:'%1 is already loaded; load anyway ?'
+                                        with:p)) ifFalse:[
+                        ^ self
+                    ].
+                    Transcript showCR:'unloading old ' , p , ' ...'.
+                    ObjectFileLoader unloadObjectFile:p. 
+                ].
+
+                Transcript showCR:'loading ' , p , ' ...'.
+                ObjectFileLoader loadObjectFile:p.
+                Class addInfoRecord:('fileIn ' , fileName) 
+            ]
+        ] ifFalse:[ ((fileName hasSuffix:'cls') 
+                     and:[((fileName mimeTypeOfContents ? '') startsWith:'application/x-smalltalk-source') not ]) ifTrue:[
+            "/ loading a binary class file
+            aStream := fileName readStream.
+            aStream notNil ifTrue:[
+                aStream fileInBinary.
+            ]
+        ] ifFalse:[
+            ((fileName hasSuffix:'class')
+            or:[(fileName hasSuffix:'cla')]) ifTrue:[
+                "/ loading a java class file
+                JavaClassReader notNil ifTrue:[
+                    JavaClassReader loadFile:(fileName pathName)
+                ]
+            ] ifFalse:[ (fileName hasSuffix:'sif') ifTrue:[
+                "/ loading a sif (smalltalk interchange format) file
+                SmalltalkInterchangeSTXFileInManager autoload.    
+                SmalltalkInterchangeFileManager newForFileIn
+                    fileName: fileName pathName;
+                    fileIn.
+            ] ifFalse:[ (fileName hasSuffix:'pcl') ifTrue:[
+                Parcel isNil ifTrue:[
+                    Dialog warn:'Parcel support not loaded.'
+                ] ifFalse:[
+                    Parcel loadParcelFrom: fileName pathName
+                ]
+            ] ifFalse:[
+                "/ loading a regular (chunk) or xml source file
+                aStream := fileName readStream.
+                aStream notNil ifTrue:[
+                    Error handle:[ : ex |
+                        Dialog warn:'Error on file in: ', ex errorString.
+                    ] do:[
+                        [
+                            Class withoutUpdatingChangesDo:[
+                                wasLazy := Compiler compileLazy:lazy.
+                                aStream fileIn.
+                            ].
+                            Class addInfoRecord:('fileIn ' , fileName asString) 
+                        ] ensure:[
+                            Compiler compileLazy:wasLazy.
+                            aStream close
+                        ]
+                    ]
+                ]
+            ]]]
+        ]]
+    ].
+! !
+
+!AbstractFileBrowser methodsFor:'menu queries cvs'!
+
+canCvsAddAndCommit
+
+    |fileItems|
+
+    fileItems := self getFileItemsFromSelection.
+    ^ (fileItems notEmpty and:[self currentFilesAreInSameDirectory]).
+!
+
+canRemoveCVSContainer
+
+    |fileItems dirOfFile cvsDir|
+
+    fileItems := self getFileItemsFromSelection.
+    fileItems isEmpty ifTrue:[^ false].
+    ^ ((fileItems detect:[:item|
+        dirOfFile := self getDirWithoutFileName:(item fileName).
+        cvsDir := dirOfFile construct:'CVS'.
+        (cvsDir isDirectory and:[cvsDir exists])
+    ] ifNone:[nil]) notNil).
+! !
+
+!AbstractFileBrowser methodsFor:'menu queries tools'!
+
+anySTFilesPresent
+
+    ^ self anyFilesPresentWithSuffix:'st'
+!
+
+canCreateNewProject
+
+    | contents |
+
+    self currentFilesAreInSameDirectory ifFalse:[^ false].
+    contents := self getItemsFromSelection.
+    ^ [ 
+        (((contents detect:[:item| item lastSuffix = 'prj'] ifNone:[nil]) isNil))
+        and:[((contents detect:[:item| item lastSuffix = 'st'] ifNone:[nil]) notNil)
+      ]]
+!
+
+canDoTerminal
+
+    ^ OperatingSystem isUNIXlike
+      or:[OperatingSystem isMSWINDOWSlike]
+!
+
+canDoTerminalAndSystemIsDOS
+
+    ^ self canDoTerminal and:[OperatingSystem isMSWINDOWSlike]
+!
+
+canDoTerminalAndSystemIsUnix
+
+    ^ self canDoTerminal and:[OperatingSystem isUNIXlike]
+!
+
+canReadAbbrevFile
+
+
+    self currentFilesAreInSameDirectory ifFalse:[^ false].
+    ^ (self currentDirectories value first construct:'abbrev.stc') exists
+!
+
+canRemoveFromSourcePath
+
+    ^ false
+!
+
+hasASN1
+    ^ [ OSI::ASN1Parser notNil 
+        and:[OSI::ASN1Parser isLoaded]]
+
+!
+
+hasASN1AndSelection
+    ^ [ self hasSelection value 
+        and:[self getFilesFromSelection size > 0
+        and:[OSI::ASN1Parser notNil 
+        and:[OSI::ASN1Parser isLoaded]]]]
+!
+
+hasCBrowser
+    ^ [ CBrowser::Browser notNil ]
+!
+
+hasJava
+
+    ^ [ JavaClassReader notNil 
+        and:[JavaClassReader isLoaded]]
+!
+
+hasJavaAndSelection
+
+    ^ [ self getFilesFromSelection size > 0
+        and:[JavaClassReader notNil 
+        and:[JavaClassReader isLoaded]]]
+!
+
+hasMP3Player
+
+    ^ [ MP3PlayerApplication notNil
+        or:[SaugFix::MP3PlayerApplication notNil ]]
+!
+
+hasMP3PlayerAndSelection
+
+    ^ [ self getFilesFromSelection size > 0
+        and:[ self hasMP3Player value]]
+!
+
+hasSlideShow
+
+    ^ [CodingExamples_GUI::SlideShow notNil]
+!
+
+hasSnapshotSelection
+
+    ^ [ 
+        | files |
+        files := self getFilesFromSelection.
+        ((files size == 1)
+        and:[ files first hasSuffix:'img' ])
+      ]
+!
+
+hasZipFileSelected
+
+    ^ [|sel item fn suff|
+
+        sel := self getItemsFromSelection.
+        sel size == 1 ifTrue:[
+            item := sel first.
+            item notNil ifTrue:[
+                suff := item suffix asLowercase.
+                suff = 'zip' or:[suff = 'jar']
+            ] ifFalse:[
+                false
+            ]
+        ] ifFalse:[
+            false
+        ]
+      ]
+!
+
+javaSupportLoaded
+
+    ^ false
+! !
+
+!AbstractFileBrowser methodsFor:'queries'!
+
+initialCommandFor:fileName into:aBox
+    "set a useful initial command for execute box."
+
+    |mime cmd select path suffix|
+
+    path := self getDirWithoutFileName:fileName.
+    suffix := fileName asFilename suffix.
+    DefaultCommandPerSuffix notNil ifTrue:[
+        cmd := DefaultCommandPerSuffix at:suffix ifAbsent:nil.
+        cmd notNil ifTrue:[
+            aBox initialText:(cmd , ' ' , fileName baseName) selectFrom:1 to:cmd size.
+            ^ self
+        ].
+    ].
+    mime := MIMETypes mimeTypeForSuffix:suffix.
+"/    mime notNil ifTrue:[
+"/        cmd := self initialCommandForMIME:mime file:path
+"/    ].
+
+    "/ XXX should be changed to take stuff from a config file
+    "/ XXX or from resources.
+
+    (path type == #regular) ifTrue:[
+        path isExecutableProgram ifTrue:[
+            aBox initialText:(fileName , ' <arguments>').
+            ^ self
+        ].
+
+        select := true.
+
+        "some heuristics - my personal preferences ...
+         (actually this should come from a configfile)"
+
+        (fileName endsWith:'akefile') ifTrue:[
+            aBox initialText:'make target' selectFrom:6 to:11.
+            ^ self
+        ].
+
+        cmd := self class defaultCommandPerMIME at:mime ifAbsent:nil.
+        cmd notNil ifTrue:[
+            select := false
+        ].
+
+        cmd isNil ifTrue:[
+
+            suffix := path suffix.
+            (suffix = 'C') ifTrue:[
+                cmd := 'g++ -c %1'.
+                select := 6.
+            ] ifFalse:[
+                suffix := suffix asLowercase.
+
+                (suffix = 'taz') ifTrue:[
+                    aBox initialText:'zcat %1 | tar tvf -'.
+                    select := false.
+                ].
+                (suffix = 'tar') ifTrue:[
+                    cmd := 'tar tvf %1'.
+                    select := 7.
+                ].
+                (suffix = 'zoo') ifTrue:[
+                    cmd := 'zoo -list %1'.
+                    select := 9.
+                ].
+                (suffix = 'zip') ifTrue:[
+                    cmd := 'unzip -l %1'.
+                    select := 8.
+                ].
+                (suffix = 'jar') ifTrue:[
+                    cmd := 'unzip -l %1'.
+                    select := 8.
+                ].
+                (suffix = 'z') ifTrue:[
+                    (fileName asLowercase endsWith:'tar.z') ifTrue:[
+                        cmd := 'zcat %1 | tar tvf -'.
+                        select := false.
+                    ] ifFalse:[
+                        cmd := 'uncompress %1'
+                    ].
+                ].
+                (suffix = 'gz') ifTrue:[
+                    (fileName asLowercase endsWith:'tar.gz') ifTrue:[
+                        cmd := ('gunzip < %1 | tar tvf -' ).
+                        select := false.
+                    ] ifFalse:[
+                        cmd := 'gunzip %1'.
+                    ].
+                ].
+                (suffix = 'html') ifTrue:[
+                    cmd := 'netscape %1'
+                ].
+                (suffix = 'htm') ifTrue:[
+                    cmd := 'netscape %1'
+                ].
+                (suffix = 'uue') ifTrue:[
+                    cmd := 'uudecode %1'
+                ].
+                (suffix = 'c') ifTrue:[
+                    cmd := 'cc -c %1'.
+                    select := 5.
+                ].
+                (suffix = 'cc') ifTrue:[
+                    cmd := 'g++ -c %1'.
+                    select := 6.
+                ].
+                (suffix = 'xbm') ifTrue:[
+                    cmd := 'bitmap %1'
+                ].
+                (suffix = 'ps') ifTrue:[
+                    cmd := 'ghostview %1'
+                ].
+                ((suffix = '1') or:[suffix = 'man']) ifTrue:[
+                    cmd := 'nroff -man %1'.
+                    select := 10.
+                ].
+            ].
+        ].
+
+        cmd isNil ifTrue:[
+            DefaultCommandPerSuffix isNil ifTrue:[
+                cmd := '<cmd>'
+            ] ifFalse:[
+                cmd := DefaultCommandPerSuffix 
+                        at:suffix
+                        ifAbsent:'<cmd>'.
+            ].
+            cmd := cmd , ' %1'.
+        ].
+
+        cmd := cmd bindWith:fileName.
+        select == false ifTrue:[
+            aBox initialText:cmd
+        ] ifFalse:[
+            select class == Interval ifTrue:[
+                aBox initialText:cmd selectFrom:select start to:select stop
+            ] ifFalse:[
+                select isInteger ifFalse:[
+                    select := (cmd indexOf:Character space ifAbsent:[cmd size + 1]) - 1.
+                ].
+                aBox initialText:cmd selectFrom:1 to:select
+            ].
+        ]
+    ]
+!
+
+isAbstractFileBrowser
+
+    ^ true
+!
+
+systemIsDOS
+
+    ^ OperatingSystem isMSDOSlike
+!
+
+systemIsUnix
+    ^ OperatingSystem isUNIXlike
+! !
+
+!AbstractFileBrowser methodsFor:'queries-file'!
+
+allItemsOfCurrentDirectory
+
+    ^ self application:#DirectoryContentsBrowser do:#allItemsOfCurrentDirectory.
+!
+
+anyFilesPresentWithSuffix:suffix
+
+    | directories |
+
+    directories := self currentDirectories value.
+    directories do:[ : dir|
+        (dir directoryContents do:[:f| (f asFilename suffix = suffix) ifTrue:[ ^ true]])
+    ].
+    ^ false.
+!
+
+currentFilesAreInSameDirectory
+
+    ^ (self currentDirectories value size == 1).
+!
+
+currentFilesHasDirectories
+
+    ^ self currentDirectories value notEmpty.
+!
+
+fileListIsEmpty
+
+    ^ self application:#DirectoryContentsBrowser do:#fileListIsEmpty.
+!
+
+fileListIsNotEmpty
+
+    ^ self fileListIsEmpty not.   
+!
+
+fileName:aFilename1 startsWith:aFilename2
+
+" check if aFilename2 starts with the same directories like aFilename1 "
+
+    | file1 file2 |
+
+    aFilename2 isNil ifTrue:[ ^ false].
+    file1 := aFilename1 asFilename.
+    file2 := aFilename2 asFilename.
+    file2 isRootDirectory ifTrue:[ ^ true].
+    ((file1 isDirectory) 
+    and:[(file2 isDirectory)
+    and:[file1 directory = file2 directory]]) ifTrue:[
+        ^ file1 baseName = file2 baseName
+    ].
+    ^ aFilename1 startsWith:aFilename2.
+!
+
+getAllFilesAsStringCollection
+
+    ^ self application:#DirectoryContentsBrowser do:#getAllFilesAsStringCollection.
+!
+
+getBestDirectory
+
+    |selFiles stringCol firstPre|
+
+    selFiles := self currentDirectories value.
+    selFiles isEmpty ifTrue:[^ nil].
+    selFiles size == 1 ifTrue:[^ selFiles first].
+    stringCol := (selFiles collect:[: file| file asString]) asOrderedCollection.
+    firstPre := stringCol at:1.
+    stringCol from:2 do:[:el|
+         firstPre :=  firstPre commonPrefixWith:el.
+    ].
+    (firstPre endsWith:(OperatingSystem fileSeparator)) ifTrue:[
+        firstPre removeLast.
+    ].
+    ^ firstPre asFilename
+!
+
+getBestFile
+
+    |selFiles stringCol firtsPre|
+
+    selFiles := self currentFileNameHolder value.
+    selFiles isEmpty ifTrue:[^ nil].
+    stringCol := selFiles collect:[: file| file asString].
+    firtsPre := stringCol at:1.
+    stringCol from:2 do:[:el|
+         firtsPre :=  firtsPre commonPrefixWith:el.
+    ].
+    ^ firtsPre asFilename
+!
+
+getDirWithoutFileName:aFileName
+
+    | dir |
+    aFileName isNil ifTrue:[
+        ^ aFileName.    
+    ].
+    dir := aFileName asFilename.
+    dir isDirectory ifFalse:[
+        dir := dir directory.
+    ].
+    ^ dir.
+!
+
+getDirectoriesForFileList:aFileCol
+
+    ^ ((aFileCol collect:[:file| self getDirWithoutFileName:file]) asSet).
+!
+
+getDirectoriesFromSelection
+
+    ^ self currentDirectories value.
+!
+
+getFileItemsFromSelection
+
+    ^ self application:#DirectoryContentsBrowser do:#getFileItemsFromSelection.
+!
+
+getFilesFromSelection
+
+    | files |
+    files := self currentFileNameHolder value.
+    ^ (files select:[: file | file isDirectory not]).
+!
+
+getFirstFileFromSelection
+
+    | files |
+    files := self currentFileNameHolder value.
+    ^ (files detect:[: file | file isDirectory not] ifNone:[nil]).
+!
+
+getFirstItemFromSelection
+
+    ^ self application:#DirectoryContentsBrowser do:#getFirstItemFromSelection.
+!
+
+getInfoItem
+    "get filename of a description-file (.dir.info, README etc.);
+     This file is automatically shown when a directory is enterred.
+     You can add more names below if you like."
+
+    |directories|
+
+    directories := self getDirectoriesFromSelection.
+    (directories size ~= 1) ifTrue:[ ^ nil].
+
+    #( 
+       '.dir.info'
+       'README'
+       'ReadMe'
+       'Readme'
+       'readme'
+       'read.me'
+       'Read.me'
+       'READ.ME'
+       'README.TXT'
+       'readme.txt'
+       'Readme.txt'
+       'Info.txt'
+       'info.txt'
+       'INFO.TXT'
+    ) do:[:f | 
+        |n|
+        n := (directories first) construct:f.
+        (n isReadable and:[n isDirectory not]) ifTrue:[
+            ^ (DirectoryContentsBrowser itemClass with:n) .
+        ]
+    ].
+    ^ nil
+!
+
+getItemsFromSelection
+
+    ^ self application:#DirectoryContentsBrowser do:#getItemsFromSelection.
+! !
+
+!AbstractFileBrowser methodsFor:'startup & release'!
+
+makeDependent
+
+    " 
+    never invoked here because there is no instance
+    "
+!
+
+masterApplication:anApplication
+
+    masterApplication isNil ifTrue:[
+        (anApplication notNil and:[anApplication askFor:#isAbstractFileBrowser]) ifTrue:[
+            super masterApplication:anApplication.
+            aspects := anApplication aspects
+        ] ifFalse:[
+            aspects isNil ifTrue:[
+                aspects := IdentityDictionary new.
+                aspects at:#applications put:(IdentityDictionary new).
+            ]
+        ].
+        self applications at:(self className) put:self.
+        self makeDependent.
+    ].
+!
+
+postOpenWith:aBuilder
+
+    super postOpenWith:aBuilder.
+! !
+
+!AbstractFileBrowser::Clipboard methodsFor:'accessing'!
+
+files
+    "return the value of the instance variable 'files' (automatically generated)"
+
+    ^ files
+!
+
+files:something
+    "set the value of the instance variable 'files' (automatically generated)"
+
+    files := something.
+!
+
+method
+    "return the value of the instance variable 'method' (automatically generated)"
+
+    ^ method
+!
+
+method:something
+    "set the value of the instance variable 'method' (automatically generated)"
+
+    method := something.
+! !
+
+!AbstractFileBrowser::CodeExecutionLock methodsFor:'accessing'!
+
+locked
+    "return the value of the instance variable 'locked' (automatically generated)"
+
+    locked isNil ifTrue:[
+        locked := false.
+    ].
+    ^ locked
+! !
+
+!AbstractFileBrowser::CodeExecutionLock methodsFor:'actions'!
+
+doIfUnLocked:aBlock
+
+    self locked ifFalse:[
+        aBlock value.
+    ].
+!
+
+doLocked:aBlock
+
+    locked  := true.
+    aBlock value.
+    locked := false.
+! !
+
+!AbstractFileBrowser::DirectoryHistory class methodsFor:'attributes access'!
+
+HistorySize
+
+    ^ 20
+! !
+
+!AbstractFileBrowser::DirectoryHistory methodsFor:'actions'!
+
+doBack
+
+    self isEmpty ifTrue:[ ^ nil ].
+    index > 1 ifTrue:[
+        index := index - 1.
+        ^ self at:index ifAbsent:nil.
+    ].
+    ^ nil
+!
+
+doForward
+
+    self isEmpty ifTrue:[ ^ nil ].
+    index < self size ifTrue:[
+        index := index + 1.
+        ^ self at:index ifAbsent:nil.
+    ].
+    ^ nil
+!
+
+setIndexTo:aFile
+
+    index := self indexOf:aFile.
+! !
+
+!AbstractFileBrowser::DirectoryHistory methodsFor:'adding & removing'!
+
+addFile:aFilename
+
+    index notNil ifTrue:[
+        ((self at:index) = aFilename) ifTrue:[^ self].
+    ].
+    (self includes:aFilename) ifTrue:[
+        "/ remove the filename to put it later after index
+        self remove:aFilename.
+    ].
+    self size > self class HistorySize ifTrue:[
+        self removeFirst.
+    ].
+    index isNil ifTrue:[
+        self add:aFilename.
+        index := 1.
+    ] ifFalse:[
+        self add:aFilename afterIndex:index.
+        index := index + 1.
+    ].
+!
+
+remove:aFilename
+
+    | indexOfFile |
+
+    indexOfFile := self indexOf:aFilename.
+    index >= indexOfFile ifTrue:[
+        index := index - 1.
+    ].
+    super remove:aFilename.
+!
+
+removeBack
+
+    index == 1 ifTrue:[^ self].
+    self removeFromIndex:1 toIndex:index - 1.
+    index := 1.
+!
+
+removeFirst
+
+    super removeFirst.
+    index ~= 1 ifTrue:[
+        index := index - 1
+    ].
+!
+
+removeForward
+
+    self removeFromIndex:(index + 1) toIndex:(self size).
+! !
+
+!AbstractFileBrowser::DirectoryHistory methodsFor:'queries'!
+
+canBack
+
+    ^ (index notNil and:[index > 1])
+!
+
+canForward
+
+    ^ (index notNil and:[(index < self size)])
+! !
+
+!AbstractFileBrowser::FilenameHistory class methodsFor:'attributes access'!
+
+FilenameHistorySize
+
+    ^ 20
+!
+
+HistorySize
+
+    ^ 20
+! !
+
+!AbstractFileBrowser::FilenameHistory methodsFor:'adding & removing'!
+
+add:aApplItem
+
+    super add:aApplItem.
+    (self size > self class FilenameHistorySize) ifTrue:[
+        self removeLast.
+    ]
+! !
+
+!AbstractFileBrowser::SaveAspectItem class methodsFor:'instance creation'!
+
+withValue:aValue isHolder:aBoolean
+
+    | instance |
+
+    instance := self basicNew.
+    instance value:aValue.
+    instance isHolder:aBoolean.
+    ^ instance
+! !
+
+!AbstractFileBrowser::SaveAspectItem methodsFor:'accessing'!
+
+isHolder
+    "return the value of the instance variable 'isHolder' (automatically generated)"
+
+    ^ isHolder
+!
+
+isHolder:something
+    "set the value of the instance variable 'isHolder' (automatically generated)"
+
+    isHolder := something.
+!
+
+value
+    "return the value of the instance variable 'value' (automatically generated)"
+
+    ^ value
+!
+
+value:something
+    "set the value of the instance variable 'value' (automatically generated)"
+
+    value := something.
+! !
+
+!AbstractFileBrowser class methodsFor:'documentation'!
+
+version
+    ^ '$Header: /cvs/stx/stx/libtool/AbstractFileBrowser.st,v 1.1 2002-09-25 07:58:48 penk Exp $'
+! !
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DirectoryTreeBrowser.st	Wed Sep 25 10:00:32 2002 +0200
@@ -0,0 +1,1053 @@
+"{ Package: 'stx:libtool' }"
+
+AbstractFileBrowser subclass:#DirectoryTreeBrowser
+	instanceVariableNames:'rootHolder dirBrowser lastResponse updateToExternFileHolderLock
+		oldDropItem expandItemTimedBlock updateTreeSelection'
+	classVariableNames:''
+	poolDictionaries:''
+	category:'Interface-Tools-File'
+!
+
+HierarchicalFileList subclass:#DirTreeBrowserHFL
+	instanceVariableNames:'draggedItem'
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:DirectoryTreeBrowser
+!
+
+!DirectoryTreeBrowser class methodsFor:'documentation'!
+
+documentation
+"
+    documentation to be added.
+
+    [author:]
+        Christian Penk (penk@bierfix)
+
+    [see also:]
+
+    [instance variables:]
+
+    [class variables:]
+"
+!
+
+examples
+"
+  Starting the application:
+                                                                [exBegin]
+    DirectoryTreeBrowser open
+
+                                                                [exEnd]
+
+  more examples to be added:
+                                                                [exBegin]
+    ... add code fragment for 
+    ... executable example here ...
+                                                                [exEnd]
+"
+! !
+
+!DirectoryTreeBrowser class methodsFor:'instance creation'!
+
+open
+
+    ^ super open
+"
+    DirectoryTreeBrowser open
+"
+!
+
+openOn:aFileName
+
+    | file |
+    file := aFileName asFilename.
+    file exists ifTrue:[
+        self openOn:aFileName withFiles:(file isDirectory not)
+    ]        
+
+"
+    DirectoryTreeBrowser openOn:Filename homeDirectory   
+    DirectoryTreeBrowser openOn:(Filename homeDirectory construct:'.bashrc')  
+"
+!
+
+openOn:aFileName withFiles:aBoolean
+
+    | instance|
+
+    instance := DirectoryTreeBrowser new.
+    instance open.
+    instance viewFilesInDirectoryTree value:aBoolean.
+    instance currentFileNameHolder value:(OrderedCollection with:aFileName).
+"
+    DirectoryTreeBrowser openOn:Filename homeDirectory  
+    DirectoryTreeBrowser openOn:(Filename homeDirectory construct:'.bashrc') withFiles:false  
+"
+! !
+
+!DirectoryTreeBrowser class methodsFor:'defaults'!
+
+timeForExpandOnDropInMilliseconds
+
+    ^ 1500
+! !
+
+!DirectoryTreeBrowser class methodsFor:'interface specs'!
+
+windowSpec
+    "This resource specification was automatically generated
+     by the UIPainter of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the UIPainter may not be able to read the specification."
+
+    "
+     UIPainter new openOnClass:DirectoryTreeBrowser andSelector:#windowSpec
+     DirectoryTreeBrowser new openInterface:#windowSpec
+     DirectoryTreeBrowser open
+    "
+
+    <resource: #canvas>
+
+    ^ 
+     #(#FullSpec
+        #name: #windowSpec
+        #window: 
+       #(#WindowSpec
+          #label: 'DirectoryTreeBrowser'
+          #name: 'DirectoryTreeBrowser'
+          #min: #(#Point 10 10)
+          #max: #(#Point 1024 768)
+          #bounds: #(#Rectangle 16 42 316 342)
+          #menu: #mainMenu
+        )
+        #component: 
+       #(#SpecCollection
+          #collection: #(
+           #(#HierarchicalListViewSpec
+              #name: 'HierarchicalListView'
+              #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
+              #model: #treeSelectionHolder
+              #menu: #menu
+              #hasHorizontalScrollBar: true
+              #hasVerticalScrollBar: true
+              #miniScrollerHorizontal: false
+              #miniScrollerVertical: false
+              #listModel: #fileList
+              #multipleSelectOk: true
+              #highlightMode: #line
+              #doubleClickSelector: #doDoubleClick:
+              #indicatorSelector: #doIndicatorClick:
+              #postBuildCallback: #postBuildDirBrowser:
+              #properties: 
+             #(#PropertyListDictionary
+                #dragArgument: #directoryTreeBrowser
+                #startDragSelector: #doStartDrag:in:
+                #displayObjectSelector: #getDisplayObjects:
+                #dropObjectSelector: #getDropObjects:
+                #dropArgument: #directoryTreeBrowser
+                #canDropSelector: #canDrop:argument:
+                #leaveSelector: #dropLeave:
+                #dropSelector: #doDrop:argument:
+              )
+            )
+           )
+         
+        )
+      )
+! !
+
+!DirectoryTreeBrowser class methodsFor:'menu specs'!
+
+menu
+    "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:DirectoryTreeBrowser andSelector:#menu
+     (Menu new fromLiteralArrayEncoding:(DirectoryTreeBrowser menu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #label: 'Copy'
+            #translateLabel: true
+            #value: #doCopy
+            #shortcutKeyCharacter: #Copy
+          )
+         #(#MenuItem
+            #label: 'Cut'
+            #translateLabel: true
+            #value: #doCut
+            #shortcutKeyCharacter: #Cut
+          )
+         #(#MenuItem
+            #label: 'Paste'
+            #translateLabel: true
+            #value: #pasteFiles
+            #enabled: #canPaste
+            #shortcutKeyCharacter: #Paste
+          )
+         #(#MenuItem
+            #label: 'Delete'
+            #translateLabel: true
+            #nameKey: #delete
+            #value: #doDelete
+            #shortcutKeyCharacter: #Delete
+          )
+         #(#MenuItem
+            #label: '-'
+          )
+         #(#MenuItem
+            #label: 'Directory Up'
+            #translateLabel: true
+            #value: #doGoDirectoryUp
+            #enabled: #enableDirectoryUp
+            #shortcutKeyCharacter: #CursorLeft
+          )
+         #(#MenuItem
+            #label: 'Set Selection Top'
+            #translateLabel: true
+            #value: #doSetSelectionToTop
+            #enabled: #selectedFileIsDirectoryAndNotRoot
+          )
+         #(#MenuItem
+            #label: 'Re-/ Expand Directory'
+            #translateLabel: true
+            #value: #expandSelectedItem
+            #shortcutKeyCharacter: #CursorRight
+          )
+         #(#MenuItem
+            #label: '-'
+          )
+         #(#MenuItem
+            #label: 'View Directory Tree'
+            #translateLabel: true
+            #isVisible: #masterIsFileBrowser
+            #indication: #showDirectoryTreeHolder
+          )
+         #(#MenuItem
+            #label: 'View Files in Directory Tree'
+            #translateLabel: true
+            #indication: #viewFilesInDirectoryTree
+          )
+         #(#MenuItem
+            #label: '-'
+          )
+         #(#MenuItem
+            #label: 'New'
+            #translateLabel: true
+            #submenuChannel: #newMenu
+          )
+         #(#MenuItem
+            #label: 'Rename...'
+            #translateLabel: true
+            #value: #treeViewFileRename
+            #shortcutKeyCharacter: #Replace
+          )
+         )
+        nil
+        nil
+      )
+! !
+
+!DirectoryTreeBrowser class methodsFor:'plugIn spec'!
+
+aspectSelectors
+    "This resource specification was automatically generated
+     by the UIPainter of ST/X."
+
+    "Do not manually edit this. If it is corrupted,
+     the UIPainter may not be able to read the specification."
+
+    "Return a description of exported aspects;
+     these can be connected to aspects of an embedding application
+     (if this app is embedded in a subCanvas)."
+
+    ^ #(
+        #selectedDirectoryModel
+      ).
+
+! !
+
+!DirectoryTreeBrowser methodsFor:'accessing'!
+
+updateToExternFileHolderLock
+    "return the value of the instance variable 'updateToExternFileHolder' (automatically generated)"
+
+    updateToExternFileHolderLock isNil ifTrue:[
+        updateToExternFileHolderLock := self class newLock.
+    ].
+    ^ updateToExternFileHolderLock
+!
+
+updateTreeSelection
+    "return the value of the instance variable 'updateToExternFileHolder' (automatically generated)"
+
+    updateTreeSelection isNil ifTrue:[
+        updateTreeSelection := self class newLock.
+    ].
+    ^ updateTreeSelection
+! !
+
+!DirectoryTreeBrowser methodsFor:'actions'!
+
+doDoubleClick:anIndex 
+    "handle a doubleClick on a directory
+    "
+
+    |item file isDirectory|
+
+    item := self fileList at:anIndex ifAbsent:nil.
+    item notNil ifTrue:[
+        isDirectory := item isDirectory.
+        file := item fileName.
+        isDirectory ifTrue:[
+            (file isReadable and:[file isExecutable]) ifTrue:[
+                self doExpand:item.
+            ]
+        ] ifFalse:[
+"/            self openApplByFileItem:item.
+        ]
+    ]
+!
+
+doExpand:anItem
+" expand the item; return true the item have expanded "
+
+    (anItem notNil and:[anItem isDirectory and:[anItem isExpanded not]]) ifTrue:[
+        anItem toggleExpand.
+        ^ true.
+    ].          
+    ^ false
+!
+
+doIndicatorClick:anIndex 
+    "handle a click on the indicator
+    "
+
+    |item|
+
+    item := self fileList at:anIndex ifAbsent:nil.
+    self toggleExpand:item
+!
+
+doUpdate
+
+    self fileList monitoringCycle.
+"/    self updateSelectedItem
+!
+
+expandSelectedItem
+
+    |selDir|
+
+    selDir := self getFirstDirectoryItemOfSelection.
+    selDir isNil ifTrue:[^ self ].
+    self toggleExpand:selDir.
+!
+
+setMatchBlock
+
+    |list|
+
+    list := self fileList.
+    self setMatchBlockForList:list
+!
+
+setMatchBlockForList:list
+
+    self viewFilesInDirectoryTree value ifTrue:[
+        list matchBlock:[:fn :isDir| isDir or:[
+                            (self showHiddenFiles value ifFalse:[
+                                (fn baseName startsWith:'.') not])
+                             and:[self filterModel value match:fn baseName]]] 
+    ] ifFalse:[
+        list matchBlock:[:fn :isDir| isDir ].
+    ].
+!
+
+toggleExpand:anItem
+
+    (anItem notNil and:[anItem isDirectory]) ifTrue:[
+        anItem toggleExpand
+    ].
+!
+
+treeViewFileRename
+    |selectedFiles|
+
+    selectedFiles := self getFilesForSelection.
+    self renameFiles:selectedFiles.
+!
+
+updateSelectedItem
+
+    | sel |
+
+    sel := self getItemsForSelection.
+    sel isEmpty ifTrue:[ ^ self].
+    sel do:[:item|
+        self doExpand:item.
+        item invalidateRepairNow:true.
+    ]
+! !
+
+!DirectoryTreeBrowser methodsFor:'aspects'!
+
+fileList
+    "holder, which keeps the current list of file entries shown by the directory-browser
+    "
+
+    |list|
+
+    (list := builder bindingAt:#fileList) isNil ifTrue:[
+        list := DirTreeBrowserHFL new.
+        list application:self.
+        list showRoot:true.
+        self setMatchBlockForList:list.
+        list directory:(self rootHolder value).
+        builder aspectAt:#fileList put:list.
+        list monitoringTaskDelay:2
+    ].
+    ^ list
+!
+
+rootHolder
+    "holder, which keeps the current root directory
+    "
+    rootHolder isNil ifTrue:[
+        rootHolder := ValueHolder new.
+        rootHolder addDependent:self.
+    ].
+    ^ rootHolder.
+! !
+
+!DirectoryTreeBrowser methodsFor:'change & update'!
+
+changeCurrentFileNameHolder
+
+    | viewFiles curFiles sel currentFileDir|
+
+    viewFiles := self viewFilesInDirectoryTree value.
+    curFiles := self currentFileNameHolder value.
+    " if i cant select the files because viewFiles is false i cant take my 
+      selction to overwrite currentFileNameHolder
+    "        
+    sel := self getFilesForSelection.
+    viewFiles not ifTrue:[
+        (self currentFilesAreInSameDirectory and:[sel size == 1]) ifTrue:[
+            currentFileDir := self getDirWithoutFileName:(self currentFileNameHolder value first).
+            (sel first = currentFileDir) ifTrue:[
+                ^ self.
+            ].
+        ].
+    ].
+    self currentFileNameHolder value:sel.
+!
+
+changeSelection
+
+    |currentHolder newItem directoryName directory oldSel index viewFiles newSel newColOfItems bestFile dir|
+
+    newSel := OrderedCollection new.
+    currentHolder := self currentFileNameHolder value.
+    currentHolder isEmpty ifTrue:[
+        self treeSelectionHolder value:newSel withoutNotifying:self.
+        ^ self
+    ].
+    bestFile := self getBestFile.
+    directory := self getDirWithoutFileName:bestFile.
+    directoryName := directory asString.
+    viewFiles := self viewFilesInDirectoryTree value.
+
+    
+    ((rootHolder value isNil) or:[((self fileName:directoryName startsWith:rootHolder value)) not]) ifTrue:[
+        self setNewRoot:directory.
+    ].
+    newColOfItems := Set new.
+    oldSel := self getItemsForSelection.
+    currentHolder do:[ : file |
+        oldSel notEmpty ifTrue:[
+            newItem := oldSel detect:[: item| item fileName = file] ifNone:[nil].
+        ].
+        newItem isNil ifTrue:[
+            ((viewFiles not) and:[file isDirectory not]) ifTrue:[
+                "/ select directory because cant select filename - if is not in tree
+                dir := self getDirWithoutFileName:file.
+                newItem := self recursiveGetItemFor:dir.
+            ] ifFalse:[
+                newItem := self recursiveGetItemFor:file.
+            ].
+        ].
+        newItem notNil ifTrue:[
+            newColOfItems add:newItem.
+        ].
+    ].
+    newSel := OrderedCollection new.
+    newColOfItems do:[ : item |
+        index := self fileList indexOf:item.
+        newSel add:index.
+    ].
+    self treeSelectionHolder value:newSel.
+    newColOfItems size == 1 ifTrue:[
+        | item |
+        item := newColOfItems first.
+        item isDirectory ifTrue:[
+            self doExpand:item.
+        ]
+    ]
+!
+
+recursiveGetItemFor:aDirectory
+
+    ^ self recursiveGetItemFor:aDirectory fromIndex:1
+!
+
+recursiveGetItemFor:aFile fromIndex:aStartIndex 
+    |list aFileNameString startIndex retItem|
+
+    list := self fileList.
+    aFileNameString := aFile asString.
+    retItem := nil.
+    list from:aStartIndex
+        do:[:item | 
+            |filename |
+
+            filename := item fileName asString.
+            (self fileName:aFileNameString startsWith:filename) ifTrue:[
+                (filename asFilename pathName = aFileNameString asFilename pathName) ifTrue:[
+                    ^ item
+                ].
+                (item isExpanded not and:[item canExpand]) ifTrue:[
+                    item toggleExpand.
+                    startIndex := list indexOf:item.
+                    retItem := self recursiveGetItemFor:aFile fromIndex:startIndex.
+                    ^ retItem
+                ]
+            ]
+        ].
+    ^ retItem
+!
+
+setNewRoot:directoryPath
+
+    | listOfFiles|
+
+    "/ EXPAND THE ROOT DIR
+    self rootHolder value:directoryPath.
+    listOfFiles := self fileList.    
+    (listOfFiles first isExpanded not) ifTrue:[
+        listOfFiles first toggleExpand.
+    ].
+!
+
+update:something with:aParameter from:aModel 
+    "one of my models changed
+    "
+
+    |list file|
+
+    " the execution of changeSelection and changeCurrentFileNameHolder must
+      lock against each other because values dont must be the same (e.g. no files
+      in tree view)
+    "
+
+    aModel == self currentFileNameHolder ifTrue:[
+        self updateTreeSelection doIfUnLocked:[
+            self updateToExternFileHolderLock doLocked:[
+                self changeSelection.
+            ].
+        ].
+        " do not return here because the AbstractFileBrowserComponent have to do something
+          for every application "  
+"/        ^ self.
+    ].
+    aModel == self treeSelectionHolder ifTrue:[
+        self updateToExternFileHolderLock doIfUnLocked:[
+            self updateTreeSelection doLocked:[
+                self changeCurrentFileNameHolder.
+            ]
+        ].
+        ^ self
+    ].
+    aModel == rootHolder ifTrue:[
+        list := self fileList.
+        file := aModel value.
+        file notNil ifTrue:[
+            file := Filename named:(file asString).
+            (file isDirectory and:[file isReadable and:[file isExecutable]]) ifTrue:[
+                list directory:file
+            ]
+        ].
+        aModel value:(list directory asString) withoutNotifying:self.
+        ^ self.
+    ].
+    aModel == self viewFilesInDirectoryTree ifTrue:[
+        self setMatchBlock.
+        "/ if changed to true select the files in currentFilenameHolder in treeview 
+        aModel value ifTrue:[
+            self changeSelection.
+        ].
+        ^ self.
+    ].
+    aModel == self filterModel ifTrue:[
+        self setMatchBlock.
+    ].
+    super update:something with:aParameter from:aModel.
+    ^ self
+! !
+
+!DirectoryTreeBrowser methodsFor:'drag & drop'!
+
+canDrop:aContext argument:arg2 
+    |source lineNr archivListDrop destinationItem dropToFile|
+
+    source := aContext dropSource.
+    source isNil ifTrue:[^ false ].
+    archivListDrop := (source argument == #archivApplication).
+    lineNr := self getLineNumberFor:aContext.
+    lineNr notNil ifTrue:[
+        destinationItem := self fileList at:lineNr ifAbsent:nil.
+    ].
+    destinationItem isNil ifTrue:[
+        oldDropItem notNil ifTrue:[
+            self removeExpandItemTimedBlock.
+            self enqueueChangeDraggedItem:nil with:aContext.
+            oldDropItem := nil.
+        ].
+        ^ false
+    ].
+    (destinationItem ~~ oldDropItem) ifTrue:[
+        oldDropItem := destinationItem.
+        self enqueueChangeDraggedItem:nil with:aContext.
+        destinationItem isDirectory ifTrue:[
+            self enqueueChangeDraggedItem:destinationItem with:aContext.
+        ].
+        self removeExpandItemTimedBlock.
+        (destinationItem notNil and:[destinationItem isDirectory and:[destinationItem fileName isWritable]]) ifTrue:[
+            expandItemTimedBlock := [
+                    self enqueueExpandForDrop:destinationItem with:aContext    
+            ].
+            Processor addTimedBlock:expandItemTimedBlock
+                afterMilliseconds:(self class timeForExpandOnDropInMilliseconds).
+            dropToFile := destinationItem fileName.
+            archivListDrop ifTrue:[
+                lastResponse := self canDropArchiv:(aContext dropObjects) for:dropToFile
+            ] ifFalse:[
+                lastResponse := self canDropFiles:(aContext dropObjects) for:dropToFile
+            ]
+        ] ifFalse:[
+            lastResponse := false
+        ]
+    ].
+    ^ lastResponse
+!
+
+changeDraggedItem:anItem with:aDropContext
+
+    self changeDraggedItem:anItem with:aDropContext saveDraw:true
+!
+
+changeDraggedItem:anItem with:aDropContext saveDraw:saveDraw
+
+    saveDraw ifTrue:[
+        aDropContext saveDraw:[
+            self fileList draggedItem:anItem.
+            self windowGroup processExposeEvents.
+        ]
+    ] ifFalse:[
+        self fileList draggedItem:anItem.
+        self windowGroup processExposeEvents.
+    ]
+!
+
+doDrop:aContext 
+    |col destination destinationPath lineNr source receiver|
+
+    source := aContext dropSource.
+    lineNr := self getLineNumberFor:aContext.
+    lineNr isNil ifTrue:[
+        ^ false
+    ].
+    destination := self fileList at:lineNr.
+    destinationPath := destination fileName.
+    source argument == #archivApplication ifTrue:[
+        receiver := source receiver.
+        receiver extractSelectedFilesTo:destinationPath askForExtractOptions:true.
+        ^ true
+    ].
+    col := OrderedCollection new.
+    aContext dropObjects do:[:obj | 
+        col add:(obj theObject)
+    ].
+    self enqueueCopyOrMoveFiles:col to:destinationPath.
+    ^ true
+!
+
+doDrop:aContext argument:arg2 
+
+    | aBoolean |
+
+    aBoolean := self doDrop:aContext.
+    self dropLeave:aContext.
+    ^ aBoolean.
+!
+
+dropLeave:aDropContext 
+    "send the last time, when leaving the widget
+    "
+    self removeExpandItemTimedBlock.
+    oldDropItem := nil.
+    self changeDraggedItem:nil with:aDropContext saveDraw:false.
+    lastResponse := nil.
+!
+
+enqueueChangeDraggedItem:anItem with:aContext 
+
+    self enqueueMessage:#'changeDraggedItem:with:' for:self arguments:(Array with:anItem with:aContext) 
+!
+
+enqueueCopyOrMoveFiles:col to:destinationPath 
+
+    self enqueueMessage:#'copyOrMoveFiles:to:' for:self arguments:(Array with:col with:destinationPath) 
+!
+
+enqueueExpandForDrop:item with:aDropContext
+
+    self enqueueMessage:#'expandForDrop:with:' for:self arguments:(Array with:item with:aDropContext) 
+!
+
+expandForDrop:item with:aDropContext
+
+    aDropContext saveDraw:[
+        (self doExpand:item) ifTrue:[
+            self windowGroup processExposeEvents
+        ].
+    ]
+!
+
+getDisplayObjects:anArgument
+
+    | string fnName sel size stream|
+    sel := self getFilesForSelection.
+    size := sel size.
+    size == 0  ifTrue:[^ ''].
+    stream := WriteStream on:''.
+    stream nextPutAll:sel first baseName.
+    size == 1 ifTrue:[
+        fnName := 'ui_menuitem.xpm'.
+    ] ifFalse:[
+        fnName := 'ui_submenu_open.xpm'.
+        stream nextPutAll:' ... '.
+        stream nextPutAll:sel last baseName.
+    ].
+    string := stream contents.
+    stream close.
+
+    fnName := 'ui_menuitem.xpm'.
+    ^ Array with:(LabelAndIcon icon:(Image fromFile:fnName)
+                             string:(Text string:string emphasis:#bold)
+                 )
+!
+
+getDropObjects:anArgument
+
+    | sel ret|
+
+    sel := self getFilesForSelection.
+    sel isEmpty ifTrue:[ ^ self ].
+    ret := sel collect:[:file| 
+        DropObject newFile:file
+    ].
+    ^ ret
+!
+
+getLineNumberFor:aDropContext
+    | yVisible|
+
+    yVisible := (aDropContext targetPoint y).
+    ^ dirBrowser yVisibleToLineNr:yVisible.
+!
+
+removeExpandItemTimedBlock
+    expandItemTimedBlock notNil ifTrue:[
+        Processor removeTimedBlock:expandItemTimedBlock.
+        expandItemTimedBlock := nil
+    ]
+! !
+
+!DirectoryTreeBrowser methodsFor:'event handling'!
+
+processEvent:anEvent
+    "filter keyboard events.
+     Return true, if I have eaten the event"
+
+    |focusView key rawKey|
+
+    anEvent isKeyPressEvent ifTrue:[
+        focusView := anEvent targetView.
+        key := anEvent key.
+        rawKey := anEvent rawKey.
+
+        (focusView isSameOrComponentOf:self window) ifTrue:[
+            focusView name = 'editField' ifTrue:[ ^ false].
+"/            (key ~= #'Alt_L') ifTrue:[self halt.].
+            (key == #CursorLeft) ifTrue:[
+                self doGoDirectoryUp.
+                ^ true
+            ].
+            (key == #CursorRight) ifTrue:[
+                self doBack.
+                ^ true
+            ].
+            (key == #Replace) ifTrue:[
+                self treeViewFileRename.
+                ^ true
+            ].
+            (key == #Delete) ifTrue:[
+                self doDelete.
+                ^ true
+            ].
+            (key == #Cut) ifTrue:[
+                self doCut.
+                ^ true
+            ].
+            (key == #Paste) ifTrue:[
+                self pasteFiles.
+                ^ true
+            ].
+            (key == #Copy) ifTrue:[
+                self doCopy.
+                ^ true
+            ].
+        ]
+    ].
+    ^ false
+! !
+
+!DirectoryTreeBrowser methodsFor:'menu - actions'!
+
+doSetSelectionToTop
+    | selDir|
+
+    selDir := self getFirstDirectoryOfSelection.
+    selDir notNil ifTrue:[
+        self rootHolder value asFilename = selDir ifTrue:[ ^ self].
+        self setNewRoot:selDir.
+        self currentFileNameHolder value:(OrderedCollection with:selDir).
+    ].
+! !
+
+!DirectoryTreeBrowser methodsFor:'queries'!
+
+getFilesForSelection
+
+    | list sel colOfFiles|
+
+    list := self fileList.
+    colOfFiles := OrderedCollection new.
+    list isEmpty ifTrue:[ ^ colOfFiles].
+    sel := self treeSelectionHolder value.
+    sel isNil ifTrue:[ ^ colOfFiles].
+
+    sel do:[: index |
+        colOfFiles add:((list at:index) fileName)
+    ].
+    ^ colOfFiles.
+!
+
+getFirstDirectoryItemOfSelection
+
+    | sel dir |
+    sel := self getItemsForSelection.
+    sel isEmpty ifTrue:[ ^ nil].
+    ^ dir := sel detect:[: el | el isDirectory ] ifNone:[nil].
+!
+
+getFirstDirectoryOfSelection
+
+    | sel dirItem |
+    sel := self getItemsForSelection.
+    sel isEmpty ifTrue:[ ^ nil].
+    dirItem := sel detect:[: el | el isDirectory ] ifNone:[nil].
+    dirItem isNil ifTrue:[^ nil].
+    ^ dirItem fileName.
+!
+
+getItemsForSelection
+
+    | list sel colOfItems|
+
+    list := self fileList.
+    colOfItems := OrderedCollection new.
+    list isEmpty ifTrue:[ ^ colOfItems].
+    sel := self treeSelectionHolder value.
+    sel isNil ifTrue:[ ^ colOfItems].
+
+    sel do:[: index |
+        colOfItems add:(list at:index)
+    ].
+    ^ colOfItems.
+!
+
+masterIsFileBrowser
+
+    ^ self masterApplication class = FileBrowserV2
+!
+
+selectedFileIsDirectoryAndNotRoot
+
+    | dir|
+
+    dir := self getFirstDirectoryOfSelection.
+    dir isNil ifTrue:[^ false].
+    ^  [(dir asString) ~= (self rootHolder value)]
+! !
+
+!DirectoryTreeBrowser methodsFor:'startup & release'!
+
+makeDependent
+
+    self currentFileNameHolder addDependent:self.
+    self notifyChannel addDependent:self.
+    self viewFilesInDirectoryTree addDependent:self.
+    self treeSelectionHolder addDependent:self.
+    self filterModel addDependent:self.
+!
+
+postBuildAsSubcanvasWith:aBuilder
+
+    super postBuildAsSubcanvasWith:aBuilder.
+!
+
+postBuildDirBrowser:aWidget
+
+    dirBrowser := aWidget scrolledView.
+    dirBrowser openEditorAction:[:ln :aGC| |field item filename newFileString rename newFilename|
+        item  := self fileList at:ln.
+
+        item label isString ifFalse:[
+            field := nil
+        ] ifTrue:[
+            field := EditField new.
+            field level:0.
+            field acceptOnReturn:true.
+            field acceptAction:[:x| 
+                filename := item fileName.
+                newFileString := x at:1.
+                filename baseName = newFileString ifFalse:[ 
+                    (self renameFile:filename to:newFileString update:false) ifTrue:[ 
+                        newFilename := filename directory construct:newFileString.
+                        item fileName:newFilename.
+                        self updateAndSelect:(OrderedCollection with:newFilename).
+                    ].
+                ].
+                aGC closeEditor.
+            ].
+            field font:(aGC font).
+            field contents:(item label).
+        ].
+        field
+    ].
+!
+
+postBuildWith:aBuilder
+
+    super postBuildWith:aBuilder.
+!
+
+postOpenAsSubcanvasWith:aBuilder
+
+    self currentFileNameHolder changed.
+    self windowGroup addPreEventHook:self.
+    ^ super postOpenAsSubcanvasWith:aBuilder.
+!
+
+postOpenWith:aBuilder
+
+    "
+    only invoked if the application not started from a master
+    "
+    self currentFileNameHolder changed.
+    self windowGroup addPreEventHook:self.
+    ^ super postOpenWith:aBuilder
+!
+
+preBuildWith:aBuilder
+
+    self masterApplication isNil ifTrue:[
+        self masterApplication:nil.
+    ].
+    ^ super preBuildWith:aBuilder.
+!
+
+release
+
+    self fileList stopMonitoringTask.
+    ^ super release.
+! !
+
+!DirectoryTreeBrowser methodsFor:'user actions'!
+
+doCopy
+    "copy current selected files/directories
+    "
+
+    self copyFilesToClipBoard:self getFilesForSelection.
+!
+
+doCut
+    "cut current selected files/directories
+    "
+    self cutFilesToClipBoard:self getFilesForSelection.
+!
+
+doDelete
+    "delete current selected files/directories
+    "
+
+    self deleteFiles:self getFilesForSelection.
+! !
+
+!DirectoryTreeBrowser::DirTreeBrowserHFL methodsFor:'accessing'!
+
+draggedItem:anItemOrNil
+" change the item icon ; return true if changed otherwise false"
+
+    |oldItem|
+
+    (anItemOrNil isNil or:[draggedItem ~~ anItemOrNil]) ifTrue:[
+        oldItem     := draggedItem.
+        draggedItem := anItemOrNil.
+
+        oldItem     ifNotNil:[ oldItem     iconChanged ].
+        draggedItem ifNotNil:[ draggedItem iconChanged ].
+        ^ true
+    ].
+    ^ false
+! !
+
+!DirectoryTreeBrowser::DirTreeBrowserHFL methodsFor:'protocol'!
+
+validateIcon:icon for:anItem
+
+    draggedItem == anItem ifTrue:[
+        ^ (FileBrowser iconForKeyMatching:#directoryOpenGray) ? icon.
+    ].
+    ^ icon
+! !
+
+!DirectoryTreeBrowser class methodsFor:'documentation'!
+
+version
+    ^ '$Header: /cvs/stx/stx/libtool/DirectoryTreeBrowser.st,v 1.1 2002-09-25 08:00:32 penk Exp $'
+! !
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FileApplicationNoteBook.st	Wed Sep 25 10:00:32 2002 +0200
@@ -0,0 +1,4455 @@
+"{ Package: 'stx:libtool' }"
+
+AbstractFileBrowser subclass:#FileApplicationNoteBook
+	instanceVariableNames:'canvasHolder selectedEditorPage listOfApplications tabMenuIndex
+		tabList selectionHistoryList privateTabList'
+	classVariableNames:''
+	poolDictionaries:''
+	category:'Interface-Tools-File'
+!
+
+AbstractFileApplicationNoteBookComponent subclass:#ArchiveViewApplication
+	instanceVariableNames:'archiveFileList enableStopButton fileTable currentSortOrder
+		selectionHolder tableColumns commandProcess errorListHolder
+		viewErrorList temporaryDirectory enableRemoveErrorOutput
+		errorListVisibilityHolder hasListEntriesHolder archiver process
+		terminateByMe columnDescriptors'
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:FileApplicationNoteBook
+!
+
+Object subclass:#ArchivItem
+	instanceVariableNames:'fileName size dateAndTime permissions icon ownerGroup method crc
+		compressSize ratio version type isDirectory'
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:FileApplicationNoteBook::ArchiveViewApplication
+!
+
+AbstractFileApplicationNoteBookComponent subclass:#CommandResult
+	instanceVariableNames:'resultStream enableStopButton process labelHolder'
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:FileApplicationNoteBook
+!
+
+AbstractFileApplicationNoteBookComponent subclass:#HtmlViewApplication
+	instanceVariableNames:'htmlView labelHolder infoLabelHolder'
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:FileApplicationNoteBook
+!
+
+AbstractFileApplicationNoteBookComponent subclass:#ImageViewApplication
+	instanceVariableNames:'imageFile imageView image fitSize fitMode'
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:FileApplicationNoteBook
+!
+
+AbstractFileApplicationNoteBookComponent subclass:#Terminal
+	instanceVariableNames:'terminalView'
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:FileApplicationNoteBook
+!
+
+AbstractFileApplicationNoteBookComponent subclass:#TextEditor
+	instanceVariableNames:'fileContentsModel doSaveFile modifiedChannel editView enableSave
+		enableReload presentation changeItemProcess closeApplication
+		semaChangeItem printAsHexDump itemChanged itemRemoved
+		enableHexToggle textEditorChangeModificationTime'
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:FileApplicationNoteBook
+!
+
+AbstractFileApplicationNoteBookComponent subclass:#XViewApplication
+	instanceVariableNames:'xView xFile vncServerPID vncPortNr vncConnection viewerPID
+		vncLock vncServerIsTerminated xItem ext'
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:FileApplicationNoteBook
+!
+
+
+!FileApplicationNoteBook class methodsFor:'application list'!
+
+applicationList
+" returns a list of all applications to start by the NoteBookApplication with 
+                #className                         #type                    
+
+            example:
+            #(  #'FooEditor'                       nil                      )
+"
+
+    ^ #(
+            #(  #'TextEditor'                      #file                    )
+            #(  #'TextEditor'                      #directoryDescription    )
+            #(  #'HtmlViewApplication'             nil                      )
+            #(  #'FindFileApplication'             nil                      )
+            #(  #'Terminal'                        nil                      )
+            #(  #'ImageViewApplication'            nil                      )
+            #(  #'ArchiveViewApplication'          nil                      )
+            #(  #'CommandResult'                   nil                      )
+            #(  #'XViewApplication'                nil                      )
+       )
+!
+
+classFor:aApplicationListItem
+    |rawName cls|
+
+    rawName := aApplicationListItem at:1.
+    (cls := self privateClassesAt:rawName) isNil ifTrue:[
+        cls := Smalltalk at:rawName.
+    ].
+    ^ cls
+!
+
+defaultApplication
+" returns the application to be started if no itemQuery returns true or no supportedSuffix is supported
+"
+
+    ^ self applicationList detect:[: applItem|
+        (((self classFor:applItem) == self textEditorClass)
+        and:[(self typeFor:applItem) == #file])
+    ] ifNone:[nil].
+!
+
+typeFor:aApplicationListItem
+
+    ^ aApplicationListItem at:2
+! !
+
+!FileApplicationNoteBook class methodsFor:'classAccess'!
+
+textEditorClass
+
+    ^ TextEditor
+! !
+
+!FileApplicationNoteBook class methodsFor:'defaults'!
+
+openAnotherApplicationOnSameItem
+
+    ^ false
+! !
+
+!FileApplicationNoteBook class methodsFor:'interface specs'!
+
+windowSpec
+    "This resource specification was automatically generated
+     by the UIPainter of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the UIPainter may not be able to read the specification."
+
+    "
+     UIPainter new openOnClass:NoteBookApplication andSelector:#windowSpec
+     NoteBookApplication new openInterface:#windowSpec
+     NoteBookApplication open
+    "
+
+    <resource: #canvas>
+
+    ^ 
+     #(#FullSpec
+        #name: #windowSpec
+        #window: 
+       #(#WindowSpec
+          #label: 'FileBrowserV2TextEditor'
+          #name: 'FileBrowserV2TextEditor'
+          #min: #(#Point 10 10)
+          #max: #(#Point 1024 768)
+          #bounds: #(#Rectangle 16 42 316 342)
+        )
+        #component: 
+       #(#SpecCollection
+          #collection: #(
+           #(#NoteBookViewSpec
+              #name: 'CommandAndTextEditor'
+              #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
+              #model: #selectedEditorPage
+              #menu: #tabList
+              #useIndex: true
+              #accessTabMenuAction: #tabMenuAt:
+              #canvas: #canvasHolder
+              #keepCanvasAlive: true
+            )
+           )
+         
+        )
+      )
+! !
+
+!FileApplicationNoteBook class methodsFor:'menu specs'!
+
+tabMenu
+    "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:FileApplicationNoteBook andSelector:#tabMenu
+     (Menu new fromLiteralArrayEncoding:(FileApplicationNoteBook tabMenu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #label: 'Close'
+            #translateLabel: true
+            #value: #doCloseApplication
+          )
+         )
+        nil
+        nil
+      )
+! !
+
+!FileApplicationNoteBook methodsFor:'accessing'!
+
+listOfApplications
+    "return the value of the instance variable 'listOfApplications' (automatically generated)"
+
+    listOfApplications isNil ifTrue:[
+        listOfApplications := OrderedCollection new.
+    ].
+    ^ listOfApplications
+!
+
+selectionHistoryList
+
+    selectionHistoryList isNil ifTrue:[
+        selectionHistoryList := OrderedCollection new.
+    ].
+    ^ selectionHistoryList
+!
+
+selectionHistoryList:aCol
+
+    selectionHistoryList := aCol 
+! !
+
+!FileApplicationNoteBook methodsFor:'accessing applications'!
+
+getAllApplicationsByClass:aClass andType:aType
+
+    ^ self listOfApplications select:[ : appl  |
+        ((appl class = aClass)
+        and:[appl type = aType])
+    ].
+!
+
+getApplicationByType:aType
+
+    ^ self listOfApplications detect:[ : appl  | 
+        (appl type == aType)
+    ] ifNone:[nil].
+!
+
+getIndexFor:aApplication
+
+    | index |
+
+    index := self listOfApplications indexOf:aApplication.
+    index ~~ 0 ifTrue:[
+        ^ index.
+    ].
+    ^ nil.
+!
+
+getSameApplicationsFor:aApplication
+
+    ^ self listOfApplications select:[ : appl |
+        ( (appl ~= aApplication)    
+        and:[ (appl isKindOf:(aApplication class)) 
+        and:[ (appl item = (aApplication item)) 
+        and:[ (appl type == aApplication type) ]]])
+    ].
+! !
+
+!FileApplicationNoteBook methodsFor:'actions-app-common'!
+
+changeItem:aItem for:aAppl
+
+    | applIndex string|
+
+    applIndex := self getIndexFor:aAppl.
+    (aItem notNil and:[aItem isDirectory not]) ifTrue:[
+        (aAppl changeItem:aItem) ifFalse:[ ^ self].
+        self fileHistory add:aItem.
+        self enableFileHistory value:true.
+    ].
+    string := aAppl getTabString.
+    self privateTabList at:applIndex put:string.
+    self doSelect:aAppl.
+!
+
+closeSubCanvas:aApplication
+
+    | applIndex historyList localHistoryList|
+
+    applIndex := self getIndexFor:aApplication.
+    applIndex notNil ifTrue:[
+"/        "/ UPDATE THE LAST SELECTION BECAUSE SEL INDEX IS DECREMENTED FOR HIGHER INDEXES
+"/        self lastSelection:applIndex.
+
+        historyList := self selectionHistoryList.
+        historyList remove:applIndex ifAbsent:nil.
+        localHistoryList := OrderedCollection new.
+        historyList notEmpty ifTrue:[
+            self selectedEditorPage value:(historyList last).
+        ] ifFalse:[
+            self selectedEditorPage value:1.
+        ].
+        historyList do:[ : index |
+            index <= applIndex ifTrue:[
+                localHistoryList add:index
+            ] ifFalse:[
+                localHistoryList add:(index - 1)
+            ]
+        ].
+        self selectionHistoryList:localHistoryList.
+        self listOfApplications removeIndex:applIndex.
+        self privateTabList removeIndex:applIndex.
+        self privateTabList isEmpty ifTrue:[
+            self viewNoteBookApplicationHolder value:false.
+            self enableViewNoteBookApplication value:false.
+        ] ifFalse:[
+            historyList notEmpty ifTrue:[
+                self selectedEditorPage value:(self selectionHistoryList last).
+            ]
+        ]
+    ].
+
+    "/ because subCanvas was configured to keep its view,
+    "/ we must destroy it here.
+    [aApplication window destroy] fork.
+!
+
+doCloseApplication
+
+    | appl |
+
+    appl := self listOfApplications at:tabMenuIndex.
+    appl doClose.
+!
+
+openApplByFileItem:aItem
+
+" use the default class list for open of applications by item "
+
+    | applList applItem itemClass|
+
+    aItem isNil ifTrue:[ ^ self ].
+    applList := self applicationList.
+    applItem := applList detect:[: aApplItem|
+        itemClass := self class classFor:aApplItem.
+        (itemClass canOpenItem:aItem).
+    ] ifNone:[nil].
+    applItem isNil ifTrue:[ ^ self openDefaultApplicationByItem:aItem].
+    applItem notNil ifTrue:[
+        |  itemType |
+        itemType := self class typeFor:applItem.
+        itemClass := self class classFor:applItem.
+        (self openApplicationClass:itemClass withItem:aItem withType:itemType) isNil ifTrue:[
+            ^ self openDefaultApplicationByItem:aItem.            
+        ].
+    ].
+!
+
+openApplicationClass:aClass withItem:aItem withType:aType
+
+    | existingAppl newAppl|
+
+    " do not open not readable items "
+    (aItem notNil and:[aItem isDirectory not and:[aItem fileName isReadable not]]) ifTrue:[
+        Dialog warn:'Can not open unreadable file ', aItem fileName baseName.
+        AbortSignal raise.
+    ].
+    existingAppl := self tryToGetExistingApplFor:aClass withItem:aItem withType:aType.
+    existingAppl notNil ifTrue:[
+        self doSelect:existingAppl.
+        ^ existingAppl
+    ].
+    newAppl := aClass new.
+    newAppl type:aType.
+    (newAppl item:aItem) ifFalse:[ ^ nil ].
+    (aItem notNil and:[aItem isDirectory not]) ifTrue:[
+        self fileHistory add:aItem.
+        self enableFileHistory value:true.
+    ].
+    self setSameFileIndexFor:newAppl.
+    self startApplication:newAppl.
+    ^ newAppl
+!
+
+openDefaultApplicationByItem:aItem
+" open the default application if no application for item is available or the start of the
+  available application failed
+"
+    | applItem |
+
+    applItem := self class defaultApplication.
+    applItem notNil ifTrue:[
+        |  itemType itemClass|
+        itemType := self class typeFor:applItem.
+        itemClass := self class classFor:applItem.
+        ^ self openApplicationClass:itemClass withItem:aItem withType:itemType.
+    ].
+    ^ nil
+!
+
+setSameFileIndexFor:anAppl
+
+    |sameFiles index item|
+
+    self class openAnotherApplicationOnSameItem not ifTrue:[
+        anAppl sameFileIndex:nil.
+        ^ self.
+    ].
+    item := anAppl item.
+    item notNil ifTrue:[
+        | hasSameFiles |
+        sameFiles := self getSameApplicationsFor:anAppl.
+        hasSameFiles := sameFiles notEmpty.
+        hasSameFiles ifTrue:[
+            (sameFiles size == 1 and:[sameFiles first sameFileIndex isNil]) ifTrue:[
+                anAppl sameFileIndex:1.
+                ^ self
+            ] ifFalse:[
+                index :=  (sameFiles collect:[:el | (el sameFileIndex ? 1)]) max.
+                anAppl sameFileIndex:index + 1.
+                ^ self
+            ]
+        ]. 
+        anAppl sameFileIndex:nil.
+    ].
+!
+
+startApplication:aApplication
+
+    | window|
+
+    aApplication masterApplication:self.
+    aApplication window ifNil:[
+        window := ApplicationSubView new.
+        aApplication createBuilder.
+        window client:aApplication.
+    ].
+    self listOfApplications add:aApplication.
+    self privateTabList add:(aApplication getTabString).
+    self viewNoteBookApplicationHolder value:true.
+    self enableViewNoteBookApplication value:true.
+    self doSelect:aApplication.
+    [
+        aApplication postOpenWith:aApplication builder.
+    ] forkAt:Processor activePriority.
+!
+
+tabStringAdd:aString for:aAppl
+
+    | index text stream|
+
+    index := self getIndexFor:aAppl.
+    index isNil ifTrue:[ ^ self].
+    text := self privateTabList at:index.
+    stream := WriteStream on:''.
+    stream nextPutAll:text.
+    stream space.
+    stream nextPutAll:aString.
+    self privateTabList at:index put:stream contents.
+    stream close.
+!
+
+tabStringChangeTo:aString for:aAppl
+
+    | index|
+
+    index := self getIndexFor:aAppl.
+    index isNil ifTrue:[ ^ self].
+    self privateTabList at:index put:aString.
+!
+
+tryToGetExistingApplFor:aClass withItem:aItem withType:aType
+
+
+    |sameAppl changeAppl selAppl|
+
+    aClass wantNewApplicationAnyway ifTrue:[^ nil].
+    sameAppl := self getAllApplicationsByClass:aClass andType:aType.
+    sameAppl isEmpty ifTrue:[^ nil].
+    ((aType == #directoryDescription) or:[aType == #commandResult]) ifTrue:[
+        changeAppl := sameAppl first.
+    ] ifFalse:[
+        (self openMultipleApplicationsForType value) ifTrue:[
+        "/ open more than one application for a class and a type
+            (self class openAnotherApplicationOnSameItem) ifTrue:[
+                "/ open a new application anyway, no matters if item already open
+                ^ nil
+            ] ifFalse:[
+                "/ if item already changed select the application
+                selAppl := sameAppl detect:[ : appl  | 
+                        (appl item = aItem) 
+                ] ifNone:[nil].
+            ].
+        ] ifFalse:[
+            "/ keep in same application change the first application of the same class and type - if item not changed otherwise open new
+                changeAppl := sameAppl detect:[ : appl  | 
+                        (appl isModified not)
+                ] ifNone:[nil].
+        ].
+    ].
+    changeAppl notNil ifTrue:[
+        self changeItem:aItem for:changeAppl.
+        selAppl := changeAppl.
+    ].
+    ^ selAppl.
+! !
+
+!FileApplicationNoteBook methodsFor:'actions-app-spec'!
+
+changeDirectoryDescription
+
+    | aInfoItem|
+
+    aInfoItem := self getInfoItem.
+    aInfoItem isNil ifTrue:[ ^ self closeDirectoryDescription ].
+    self openDirectoryDescription.
+!
+
+closeDirectoryDescription
+
+    | dirContApll |
+
+    dirContApll := self getApplicationByType:#directoryDescription.
+    dirContApll notNil ifTrue:[
+        dirContApll doClose.
+    ].
+!
+
+openArchiveViewApplication:aItem
+
+    | result |
+    result := self openApplicationClass:ArchiveViewApplication withItem:aItem withType:nil.
+    result isNil ifTrue:[
+        Dialog warn:'file type of ', aItem fileName baseName, ' not yet supported'.
+        ^ self.
+    ].
+!
+
+openCommandResultApplication
+
+
+    ^ self openApplicationClass:CommandResult withItem:nil withType:#commandResult
+!
+
+openDirectoryDescription
+
+    | appl aInfoItem|
+
+    aInfoItem := self getInfoItem.
+    aInfoItem notNil ifTrue:[
+        appl := self openTextEditorOn:aInfoItem type:#directoryDescription.
+    ].
+!
+
+openSearchFileOn:aItem
+
+    ^ self openApplicationClass:FindFileApplication withItem:aItem withType:nil
+!
+
+openTerminalApplication:aItem
+
+    ^ self openApplicationClass:Terminal withItem:aItem withType:nil
+!
+
+openTextEditorOn:aItem 
+
+    ^ self openTextEditorOn:aItem type:#file 
+!
+
+openTextEditorOn:aItem type:aDirDescrOrFile
+
+    ^ self openApplicationClass:TextEditor withItem:aItem withType:aDirDescrOrFile
+! !
+
+!FileApplicationNoteBook methodsFor:'applicationlist access'!
+
+applicationList
+    ^ self class applicationList
+! !
+
+!FileApplicationNoteBook methodsFor:'aspects'!
+
+canvasHolder
+
+    canvasHolder isNil ifTrue:[
+        canvasHolder := ValueHolder new.
+    ].
+    ^ canvasHolder.
+!
+
+privateTabList
+
+    privateTabList isNil ifTrue:[
+        privateTabList := List new.
+        privateTabList addDependent:self.
+    ].
+    ^ privateTabList.
+!
+
+selectedEditorPage
+
+    selectedEditorPage isNil ifTrue:[
+        selectedEditorPage := ValueHolder new.
+"/ if your app needs to be notified of changes, uncomment one of the lines below:
+       selectedEditorPage addDependent:self.
+"/       selectedEditorPage onChangeSend:#selectedEditorPageChanged to:self.
+    ].
+    ^ selectedEditorPage.
+!
+
+tabList
+
+    tabList isNil ifTrue:[
+        tabList := (List new) asValue.
+    ].
+    ^ tabList.
+!
+
+tabList:aValue
+
+    tabList := aValue.
+! !
+
+!FileApplicationNoteBook methodsFor:'change & update'!
+
+update:something with:aParameter from:changedObject
+    "Invoked when an object that I depend upon sends a change notification."
+
+    "stub code automatically generated - please change as required"
+
+    | appl sel viewDirDescr|
+
+
+    changedObject == self currentDirectories ifTrue:[
+        self viewDirectoryDescription value ifTrue:[
+            self changeDirectoryDescription.  
+        ].
+        ^ self.
+    ].
+    changedObject == self viewDirectoryDescription ifTrue:[
+        viewDirDescr := changedObject value.
+        viewDirDescr ifTrue:[
+            self openDirectoryDescription.
+        ] ifFalse:[
+            self closeDirectoryDescription.
+        ].
+        ^ self.
+    ].
+    changedObject == self privateTabList ifTrue:[
+        | privateListOfTabs |
+        privateListOfTabs := changedObject.
+        privateListOfTabs size > 1 ifTrue:[
+            self tabList value:privateListOfTabs.
+            self tabList changed.
+        ] ifFalse:[
+            self tabList value:nil.
+        ].
+        ^ self
+    ].
+    changedObject == self selectedEditorPage ifTrue:[
+        | listOfEdits indexOfLastSel list |
+
+        sel := changedObject value.
+        "/ dont want the tabs with one application - thats why i have to change my tablist
+        "/ sel goes to if - i want select the last selection
+        sel = 0 ifTrue:[
+            ^ self.
+        ].
+        list := self selectionHistoryList.
+        (list includes:sel) ifTrue:[
+            list remove:sel
+        ].
+        list add:sel.
+        self selectionHistoryList:list.
+        appl := self listOfApplications at:sel.
+        self doSelect:appl.
+    ].
+
+    ^ super update:something with:aParameter from:changedObject
+! !
+
+!FileApplicationNoteBook methodsFor:'menu & actions'!
+
+tabMenuAt:aTab
+
+    |menu|
+
+    menu :=  Menu new fromLiteralArrayEncoding:self class tabMenu.
+    menu ifNil:[ ^ nil ].
+    tabMenuIndex := aTab.
+    menu receiver:self.
+    ^ menu
+! !
+
+!FileApplicationNoteBook methodsFor:'queries'!
+
+getSameFilesModifiedFor:aAppl
+
+    | sameFileAppl colOfChanged |
+
+    sameFileAppl := self getSameApplicationsFor:aAppl.
+    sameFileAppl notEmpty ifTrue:[
+        colOfChanged := OrderedCollection new.
+        sameFileAppl do:[ : el |
+            el modifiedChannel value ifTrue:[
+                colOfChanged add:el.
+            ]
+        ]
+    ].
+    ^ colOfChanged
+! !
+
+!FileApplicationNoteBook methodsFor:'selection'!
+
+doSelect:anAppl
+
+    | index fileName|
+
+    fileName := anAppl fileName.
+    fileName notNil ifTrue:[
+        self changeFileBrowserTitleTo:fileName baseName.
+    ].
+    index := self getIndexFor:anAppl.
+
+    index notNil ifTrue:[
+        canvasHolder value:(anAppl window).
+        self selectedEditorPage value:index.
+    ]
+! !
+
+!FileApplicationNoteBook methodsFor:'startup & release'!
+
+makeDependent
+
+    self viewDirectoryDescription addDependent:self.
+    self currentDirectories addDependent:self.
+!
+
+postOpenAsSubcanvasWith:aBuilder
+
+    self viewDirectoryDescription changed.
+    ^ super postOpenAsSubcanvasWith:aBuilder.
+!
+
+postOpenWith:aBuilder
+
+    "
+    only invoked if the application not started from a master
+    "
+    self openTextEditorOn:(DirectoryContentsBrowser itemClass with:(Filename homeDirectory construct:'.bashrc')).
+    ^ super postOpenWith:aBuilder
+!
+
+preBuildWith:aBuilder
+
+    self masterApplication isNil ifTrue:[
+        self masterApplication:nil.
+    ].
+    ^ super preBuildWith:aBuilder.
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication class methodsFor:'common options'!
+
+SupportedFiles
+
+    | dict |
+    dict := Dictionary new.
+
+    #(
+        'application/x-tar-compressed'      tarGZipArchive
+        'application/x-tar'                 tarArchive
+        'application/x-gzip-compressed'     gzipArchive
+        'application/x-zip-compressed'      zipArchive
+    ) pairWiseDo:[ : mimeType :classSelector |
+        dict at:mimeType put:classSelector.
+    ].
+    ^ dict
+!
+
+classSelectorFor:aItem
+
+    | class |
+    aItem hasMimeType ifFalse:[^nil].
+    class := self SupportedFiles at:(aItem mimeType) ifAbsent:nil.
+    class isNil ifTrue:[
+        (aItem lastButOneSuffix = 'tar' and:[aItem lastSuffix = 'gz']) ifTrue:[
+            class := #tarGZipArchive.
+        ].
+    ].
+    ^ class.
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication class methodsFor:'defaults'!
+
+tabStringFor:aApplicationType
+
+    ^ 'Archive for:'
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication class methodsFor:'image specs'!
+
+removeError
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self removeError inspect
+     ImageEditor openOnClass:self andSelector:#removeError
+     Icon flushCachedIcons
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'FileApplicationNoteBook::ArchiveViewApplication class removeError'
+        ifAbsentPut:[(Depth8Image new) width: 28; height: 22; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+@@@@@@@@@@@FA @@@@@@@@XF@@@@@@@@@@@@@@@@@@@@@@@@@@XF@@@@@@XF@@@@@@@@@@@@@@@@@@@@@@@@@@@@A X@@@XF@@@@@@@@@@@@@@@@@@@@@@@@
+@@@@@@@FA XF@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@XF@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@XFA X@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@XF
+@@@FA @@@@@@@@@@@@@@@@@@@@@@@@@@@@XF@@@@@@XF@@@@@@@@@@@@@@@@@@@@@@@@@@XF@@@@@@@@A X@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; colorMapFromArray:#[0 0 0 8 4 8 105 133 190 121 133 157 129 129 129 194 194 194 255 0 0]; mask:((Depth1Image new) width: 28; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@LC@@@A!! @@@L0@@@A8@@@@L@@@@G @@@CL@@@A!! @@@0L@@@@@@@BY=5LAIUUT S5UU8D!!UUPAFU\#@@@@@@@LR9@@D)J @A:R(@@P$*@@CIN @@@@@@@@@a') ; yourself); yourself]
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication class methodsFor:'interface specs'!
+
+windowSpec
+    "This resource specification was automatically generated
+     by the UIPainter of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the UIPainter may not be able to read the specification."
+
+    "
+     UIPainter new openOnClass:NoteBookApplication::ArchiveViewApplication andSelector:#windowSpec
+     NoteBookApplication::ArchiveViewApplication new openInterface:#windowSpec
+     NoteBookApplication::ArchiveViewApplication open
+    "
+
+    <resource: #canvas>
+
+    ^ 
+     #(#FullSpec
+        #name: #windowSpec
+        #window: 
+       #(#WindowSpec
+          #label: 'Archive Application'
+          #name: 'Archive Application'
+          #min: #(#Point 10 10)
+          #max: #(#Point 1024 768)
+          #bounds: #(#Rectangle 12 22 688 514)
+          #menu: #mainMenu
+        )
+        #component: 
+       #(#SpecCollection
+          #collection: #(
+           #(#MenuPanelSpec
+              #name: 'MenuTerminal'
+              #layout: #(#LayoutFrame 0 0.0 0 0 0 1.0 32 0)
+              #menu: #menu
+              #textDefault: true
+            )
+           #(#'FileBrowserV2UISpecifications::PanelSpec'
+              #name: 'VerticalPanel'
+              #layout: #(#LayoutFrame 0 0.0 32 0.0 0 1.0 0 1.0)
+              #borderWidth: 1
+              #whichView: #last
+              #orientation: #vertical
+              #visibility: #errorListVisibilityHolder
+              #component: 
+             #(#SpecCollection
+                #collection: #(
+                 #(#DataSetSpec
+                    #name: 'Table1'
+                    #model: #selectionHolder
+                    #menu: #fileListMenu
+                    #hasHorizontalScrollBar: true
+                    #hasVerticalScrollBar: true
+                    #dataList: #archiveFileList
+                    #useIndex: false
+                    #has3Dsepartors: false
+                    #doubleClickSelector: #dblClick
+                    #columnHolder: #tableColumns
+                    #multipleSelectOk: true
+                    #verticalSpacing: 0
+                    #postBuildCallback: #postBuildFileTable:
+                    #properties: 
+                   #(#PropertyListDictionary
+                      #dragArgument: #archivApplication
+                      #startDragSelector: #doStartDrag:in:
+                      #displayObjectSelector: #getDisplayObjects:
+                      #dropObjectSelector: #getDropObjects:
+                      #dropArgument: #archivApplication
+                      #canDropSelector: #canDrop:argument:
+                      #dropSelector: #doDrop:argument:
+                    )
+                  )
+                 #(#SequenceViewSpec
+                    #name: 'ErrorList'
+                    #initiallyDisabled: true
+                    #hasHorizontalScrollBar: true
+                    #hasVerticalScrollBar: true
+                    #backgroundColor: #(#Color 100.0 100.0 100.0)
+                    #isMultiSelect: true
+                    #useIndex: false
+                    #sequenceList: #errorListHolder
+                  )
+                 )
+               
+              )
+              #handles: #(#Any 0.5 1.0)
+            )
+           )
+         
+        )
+      )
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication class methodsFor:'menu specs'!
+
+fileListMenu
+    "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:NoteBookApplication::ArchiveViewApplication andSelector:#fileListMenu
+     (Menu new fromLiteralArrayEncoding:(NoteBookApplication::ArchiveViewApplication fileListMenu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #label: 'Extract to Directory'
+            #translateLabel: true
+            #value: #extractAll
+            #enabled: #hasSelectionInList
+          )
+         #(#MenuItem
+            #label: 'Delete from Archiv'
+            #translateLabel: true
+            #value: #removeFilesFromArchiv
+            #enabled: #canDelete
+            #shortcutKeyCharacter: #Delete
+          )
+         #(#MenuItem
+            #label: 'View'
+            #translateLabel: true
+            #isVisible: #isEmbeddedApplication
+            #value: #viewFile
+            #enabled: #hasOneSelectionInList
+          )
+         #(#MenuItem
+            #label: 'Copy Filenames'
+            #translateLabel: true
+            #value: #copyFilesToClipboard
+            #enabled: #hasSelectionInList
+          )
+         #(#MenuItem
+            #label: 'Select All'
+            #translateLabel: true
+            #value: #selectAll
+            #enabled: #hasListEntriesHolder
+          )
+         )
+        nil
+        nil
+      )
+!
+
+menu
+    "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:FileApplicationNoteBook::ArchiveViewApplication andSelector:#menu
+     (Menu new fromLiteralArrayEncoding:(FileApplicationNoteBook::ArchiveViewApplication menu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #label: 'Stop'
+            #translateLabel: true
+            #isButton: true
+            #nameKey: #Stop
+            #value: #doStopProcess
+            #enabled: #enableStopButton
+            #labelImage: #(#ResourceRetriever #ToolbarIconLibrary #stop22x22Icon)
+          )
+         #(#MenuItem
+            #label: 'Exctract'
+            #translateLabel: true
+            #isButton: true
+            #value: #extractAll
+            #enabled: #hasListEntriesHolder
+            #labelImage: #(#ResourceRetriever #ToolbarIconLibrary #extract28x28Icon)
+          )
+         #(#MenuItem
+            #label: 'Remove Output'
+            #translateLabel: true
+            #isButton: true
+            #value: #removeErrorOutput
+            #enabled: #enableRemoveErrorOutput
+            #labelImage: #(#ResourceRetriever nil #removeError)
+          )
+         #(#MenuItem
+            #label: 'Close'
+            #translateLabel: true
+            #isButton: true
+            #hideMenuOnActivated: false
+            #isVisible: #isEmbeddedApplication
+            #startGroup: #right
+            #value: #doClose
+            #labelImage: #(#ResourceRetriever #AbstractFileBrowser #closeIcon)
+          )
+         )
+        nil
+        nil
+      )
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication class methodsFor:'queries'!
+
+canOpenItem:aItem
+
+    ^ (aItem hasMimeType and:[(aItem mimeType isArchiv) and:[OperatingSystem isUNIXlike]])
+!
+
+wantNewApplicationAnyway
+
+    ^ false
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication class methodsFor:'tableColumns specs'!
+
+tableColumns
+    "This resource specification was automatically generated
+     by the DataSetBuilder of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the DataSetBuilder may not be able to read the specification."
+
+    "
+     DataSetBuilder new openOnClass:NoteBookApplication::ArchiveViewApplication andSelector:#tableColumns
+    "
+
+    <resource: #tableColumns>
+
+    ^#(
+      #(#DataSetColumnSpec
+         #id: 'icon'
+         #labelButtonType: #Button
+         #labelActionSelector: #sortList:
+         #labelActionArgument: 'directory'
+         #width: 25
+         #minWidth: 20
+         #height: 16
+         #model: #icon
+         #canSelect: false
+         #isResizeable: false
+         #showRowSeparator: false
+         #showColSeparator: false
+       )
+      #(#DataSetColumnSpec
+         #label: 'File Name'
+         #id: 'fileName'
+         #labelAlignment: #left
+         #labelButtonType: #Button
+         #labelActionSelector: #sortList:
+         #labelActionArgument: 'fileName'
+         #model: #fileName
+         #canSelect: false
+         #showRowSeparator: false
+         #showColSeparator: false
+       )
+      #(#DataSetColumnSpec
+         #label: 'Perm'
+         #id: 'permissions'
+         #labelButtonType: #Button
+         #labelActionSelector: #sortList:
+         #labelActionArgument: 'permissions'
+         #usePreferredWidth: true
+         #width: 75
+         #model: #permissions
+         #canSelect: false
+         #showRowSeparator: false
+         #showColSeparator: false
+       )
+      #(#DataSetColumnSpec
+         #label: 'Version'
+         #id: 'version'
+         #labelButtonType: #Button
+         #labelActionSelector: #sortList:
+         #labelActionArgument: 'version'
+         #columnAlignment: #right
+         #width: 100
+         #minWidth: 50
+         #model: #version
+         #canSelect: false
+         #showRowSeparator: false
+         #showColSeparator: false
+       )
+      #(#DataSetColumnSpec
+         #label: 'Type'
+         #id: 'type'
+         #labelButtonType: #Button
+         #labelActionSelector: #sortList:
+         #labelActionArgument: 'type'
+         #columnAlignment: #right
+         #width: 100
+         #minWidth: 50
+         #model: #type
+         #canSelect: false
+         #showRowSeparator: false
+         #showColSeparator: false
+       )
+      #(#DataSetColumnSpec
+         #label: 'Owner/Group'
+         #id: 'ownerGroup'
+         #labelButtonType: #Button
+         #labelActionSelector: #sortList:
+         #labelActionArgument: 'ownerGroup'
+         #columnAlignment: #right
+         #width: 100
+         #minWidth: 50
+         #model: #ownerGroup
+         #canSelect: false
+         #showRowSeparator: false
+         #showColSeparator: false
+       )
+      #(#DataSetColumnSpec
+         #label: 'Size'
+         #id: 'size'
+         #labelButtonType: #Button
+         #labelActionSelector: #sortList:
+         #labelActionArgument: 'sizeAsNumber'
+         #columnAlignment: #right
+         #width: 80
+         #model: #size
+         #canSelect: false
+         #showRowSeparator: false
+         #showColSeparator: false
+       )
+      #(#DataSetColumnSpec
+         #label: 'Date & Time'
+         #id: 'dateAndTime'
+         #labelAlignment: #right
+         #labelButtonType: #Button
+         #labelActionSelector: #sortList:
+         #labelActionArgument: 'dateAndTime'
+         #columnAlignment: #right
+         #usePreferredWidth: true
+         #width: 140
+         #model: #dateAndTime
+         #canSelect: false
+         #showRowSeparator: false
+         #showColSeparator: false
+       )
+      #(#DataSetColumnSpec
+         #label: 'Method'
+         #id: 'method'
+         #labelButtonType: #Button
+         #labelActionSelector: #sortList:
+         #labelActionArgument: 'method'
+         #columnAlignment: #center
+         #usePreferredWidth: true
+         #width: 140
+         #model: #method
+         #canSelect: false
+         #showRowSeparator: false
+         #showColSeparator: false
+       )
+      #(#DataSetColumnSpec
+         #label: 'CRC'
+         #id: 'crc'
+         #labelButtonType: #Button
+         #labelActionSelector: #sortList:
+         #labelActionArgument: 'crc'
+         #usePreferredWidth: true
+         #width: 140
+         #model: #crc
+         #canSelect: false
+         #showRowSeparator: false
+         #showColSeparator: false
+       )
+      #(#DataSetColumnSpec
+         #label: 'Compress Size'
+         #id: 'compressSize'
+         #labelButtonType: #Button
+         #labelActionSelector: #sortList:
+         #labelActionArgument: 'compressSize'
+         #usePreferredWidth: true
+         #width: 140
+         #model: #compressSize
+         #canSelect: false
+         #showRowSeparator: false
+         #showColSeparator: false
+       )
+      #(#DataSetColumnSpec
+         #label: 'Ratio'
+         #id: 'ratio'
+         #labelButtonType: #Button
+         #labelActionSelector: #sortList:
+         #labelActionArgument: 'ratio'
+         #usePreferredWidth: true
+         #width: 140
+         #model: #ratio
+         #canSelect: false
+         #showRowSeparator: false
+         #showColSeparator: false
+       )
+      )
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication methodsFor:'accessing'!
+
+archiver
+    "return the value of the instance variable 'archiver' (automatically generated)"
+
+    ^ archiver
+!
+
+archiver:something
+    "set the value of the instance variable 'archiver' (automatically generated)"
+
+    archiver := something.
+!
+
+columnDescriptors
+    "return the value of the instance variable 'columnDescriptors' (automatically generated)"
+
+    ^ columnDescriptors
+!
+
+columnDescriptors:aListOfColumns
+    "set the value of the instance variable 'columnDescriptors' (automatically generated)"
+
+    columnDescriptors = aListOfColumns ifTrue:[
+        ^ self
+    ].
+
+    columnDescriptors    := OrderedCollection new.
+
+    aListOfColumns keysAndValuesDo:[:anIndex :aDesc| |col|
+        col := aDesc isSequenceable ifTrue:[DataSetColumnSpec new fromLiteralArrayEncoding:aDesc]
+                                   ifFalse:[aDesc].
+        columnDescriptors add:col.
+    ].
+!
+
+item:aItem
+    "set the value of the instance variable 'item' (automatically generated)"
+
+    | classSelector|
+    
+    super item:aItem.
+    classSelector := self class classSelectorFor:aItem.
+    (classSelector notNil and:[(Archiver respondsTo:classSelector) notNil]) ifTrue:[
+        self makeProcessFor:[
+            self archiver:((Archiver perform:classSelector) with:(self fileName)).
+            self setColumnsForArchiver.
+        ] with:'setup archiv'.
+        ^ true
+    ]. 
+    ^ false
+!
+
+temporaryDirectory
+    "return the value of the instance variable 'temporaryDirectory' (automatically generated)"
+
+    temporaryDirectory isNil ifTrue:[
+        temporaryDirectory := Filename newTemporary.
+        temporaryDirectory makeDirectory.
+    ].
+    ^ temporaryDirectory
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication methodsFor:'actions'!
+
+changeItem:aItem
+
+    self item:aItem.
+    self emptyList.
+    self listAllFilesFromArchiv.
+    ^ true
+!
+
+copyFilesToClipboard
+
+
+    |sel list stream|
+
+    sel := self selectionHolder value.
+    list := self archiveFileList.
+    (sel notNil and:[sel notEmpty]) ifTrue:[
+        stream := WriteStream on:''.
+        sel do:[: key |
+            stream nextPutAll:(key fileName asString).
+            stream cr.
+        ].
+        self window setTextSelection:stream contents.
+        stream close.
+    ].
+!
+
+dblClick
+
+    self viewFile.
+!
+
+doStopProcess
+
+    | archiver |
+    self stopProcess.
+    archiver := self archiver.
+    archiver notNil ifTrue:[
+        self archiver stopProcess.
+    ].
+    self enableStopButton value:false.
+!
+
+emptyList
+
+    self archiveFileList value removeAll.
+!
+
+removeErrorOutput
+
+    self viewErrorList value:false.
+    self errorListHolder removeAll.
+!
+
+removeTemporaryDirectory
+
+    | tmp |
+
+    temporaryDirectory notNil ifTrue:[
+        tmp := self temporaryDirectory.
+        (FileDirectory directoryNamed:(tmp directory)) removeDirectory:tmp baseName.
+        temporaryDirectory := nil.
+    ].
+!
+
+selectAll
+
+    | sel listOfFiles|
+
+    sel := OrderedCollection new.
+    listOfFiles := self archiveFileList value.
+    1 to:(listOfFiles size) do:[ : el |
+        sel add:el
+    ].
+    self selectionHolder value:sel.
+!
+
+updateFileBrowserIfPresentWith:aDirectory
+
+    | master|
+
+    master := self masterApplication.
+    master notNil ifTrue:[
+        master updateAndSelect:(OrderedCollection with:aDirectory).
+    ].
+!
+
+viewFile
+
+    | master item file tempDir|
+
+    master := self masterApplication.
+    self selectionHolder value size = 1 ifFalse:[
+        Dialog warn:'only one file have to be selected'.
+        ^ self.
+    ].
+    tempDir := self temporaryDirectory.
+    self extractSelectedFilesTo:tempDir askForExtractOptions:false.
+    process notNil ifTrue:[
+        process waitUntilTerminated.
+    ].
+    file := tempDir construct:self selectionHolder value first fileName.
+    file exists ifTrue:[
+        item := DirectoryContentsBrowser itemClass with:file.
+    ].
+    master notNil ifTrue:[
+        master openApplByFileItem:item.
+    ].
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication methodsFor:'aspects'!
+
+archiveFileList
+
+    archiveFileList isNil ifTrue:[
+        archiveFileList := List new.
+        archiveFileList addDependent:self.
+    ].
+    ^ archiveFileList.
+!
+
+enableRemoveErrorOutput
+    "return/create the 'enableRemoveErrorOutput' value holder (automatically generated)"
+
+    enableRemoveErrorOutput isNil ifTrue:[
+        enableRemoveErrorOutput := false asValue.
+    ].
+    ^ enableRemoveErrorOutput
+!
+
+enableStopButton
+
+    enableStopButton isNil ifTrue:[
+        enableStopButton := false asValue.
+    ].
+    ^ enableStopButton
+!
+
+errorListHolder
+
+    errorListHolder isNil ifTrue:[
+        errorListHolder := List new.
+    ].
+    ^ errorListHolder.
+!
+
+errorListVisibilityHolder
+
+    errorListVisibilityHolder isNil ifTrue:[
+        errorListVisibilityHolder := false asValue.
+    ].
+    ^ errorListVisibilityHolder
+!
+
+hasListEntriesHolder
+    "return/create the 'hasListEntriesHolder' value holder (automatically generated)"
+
+    hasListEntriesHolder isNil ifTrue:[
+        hasListEntriesHolder := false asValue.
+    ].
+    ^ hasListEntriesHolder
+!
+
+hasOneSelectionInList
+
+    | sel |
+    sel := self selectionHolder value.
+    ^ (sel notNil and:[sel notEmpty and:[sel size = 1]])
+!
+
+hasSelectionInList
+
+    | sel |
+    sel := self selectionHolder value.
+    ^ (sel notNil and:[sel notEmpty])
+!
+
+selectionHolder
+
+    selectionHolder isNil ifTrue:[
+        selectionHolder := ValueHolder new.
+        selectionHolder addDependent:self.
+    ].
+    ^ selectionHolder.
+!
+
+tableColumns
+
+    tableColumns isNil ifTrue:[
+        tableColumns := self class tableColumns asValue.
+    ].
+    ^ tableColumns.
+!
+
+viewErrorList
+    "return/create the 'viewErrorList' value holder (automatically generated)"
+
+    viewErrorList isNil ifTrue:[
+        viewErrorList := false asValue.
+        viewErrorList onChangeSend:#viewErrorListChanged to:self.
+    ].
+    ^ viewErrorList
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication methodsFor:'change & update'!
+
+update:something with:aParameter from:changedObject
+    "Invoked when an object that I depend upon sends a change notification."
+
+    "stub code automatically generated - please change as required"
+
+    changedObject == self archiveFileList ifTrue:[
+        self hasListEntriesHolder value:(changedObject notEmpty).
+        ^ self
+    ].
+    super update:something with:aParameter from:changedObject
+!
+
+viewErrorListChanged
+
+    | viewListValue|
+
+    viewListValue := self viewErrorList value.
+    self enableRemoveErrorOutput value:viewListValue.
+    self errorListVisibilityHolder value:viewListValue.
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication methodsFor:'command execution'!
+
+getErrorBlock
+
+    ^
+    [: x |
+        self viewErrorList value:true.
+        self errorListHolder value add:x.
+    ]
+!
+
+getErrorStream
+
+    |errStream|
+
+    errStream := ActorStream new.
+    errStream nextPutLineBlock:(self getErrorBlock).
+    ^ errStream
+!
+
+getOutBlock
+
+    |firstLineNotReaded key|
+
+    firstLineNotReaded := true.
+    ^ [: line |
+        | words ownerGroup item archiverColumns itemWriter index itemWordCount|
+
+        (firstLineNotReaded and:[archiver class hasTitleLine]) ifTrue:[
+            firstLineNotReaded := false.
+        ]ifFalse:[
+            words := line asCollectionOfWords.
+            archiverColumns := archiver class columns.
+            item := ArchivItem new.
+            index := 1.
+            archiverColumns do:[:colDescr |
+                | itemStream |
+                itemWordCount := colDescr second.
+                itemWriter := ((colDescr first) asString, ':') asSymbol.
+                itemStream := WriteStream on:''.
+                index to:(index + itemWordCount - 1) do:[:i|
+                    itemStream nextPutAll:(words at:i).
+                    itemStream space.
+                ].
+                item perform:itemWriter with:(itemStream contents).
+                itemStream close.
+                index := index + itemWordCount.
+            ].
+            ((archiverColumns collect:[:el| el first]) includes:#permissions) ifTrue:[
+                (item permissions startsWith:$d) ifTrue:[
+                    key := #directory.
+                    item isDirectory:true.
+                ] ifFalse:[
+                    key := MIMETypes mimeTypeForFilename:(item fileName asFilename baseName).
+                    item isDirectory:false.
+                ].
+            ] ifFalse:[
+                key := MIMETypes mimeTypeForFilename:(item fileName asFilename baseName).
+            ].
+            item icon:(FileBrowser iconForKeyMatching:key).
+            self archiveFileList value add:item
+        ].
+    ]
+!
+
+getOutStream
+
+    |outStream|
+
+    outStream := ActorStream new.
+    outStream nextPutLineBlock:(self getOutBlock).
+    ^ outStream
+!
+
+makeProcessFor:aBlock
+
+    self makeProcessFor:aBlock with:''
+!
+
+makeProcessFor:aBlock with:string
+
+    | locBlock |
+
+    process notNil ifTrue:[
+        process waitUntilTerminated.
+        terminateByMe ifTrue:[
+            terminateByMe := false.
+            ^ self
+        ].
+    ].
+    locBlock := [   [        
+                    self notifyChannel value:string.
+                    aBlock value.
+                    self notifyChannel value:''.
+                    ] valueNowOrOnUnwindDo:[ 
+                        process := nil.
+                        self enableStopButton value:false.
+                    ] 
+                ].
+    process := locBlock newProcess.
+    process priority:(Processor systemBackgroundPriority).
+    process name:'ArchiveApplicationProcess'.
+    self enableStopButton value:true.
+    process resume.
+!
+
+setColumnsForArchiver
+
+    | newColumns archiverColumns allColumns iconColumn|
+
+    archiverColumns := archiver class columns collect:[:el| el  first].
+    allColumns := OrderedCollection new.
+    newColumns := OrderedCollection new.
+    self class tableColumns do:[:el|
+        allColumns add:(DataSetColumnSpec new fromLiteralArrayEncoding:el).
+    ].
+    iconColumn := allColumns detect:[: col | (col id asSymbol) = #icon] ifNone:[nil].
+    iconColumn notNil ifTrue:[
+        newColumns add:iconColumn.
+    ].
+    allColumns do:[:col|
+        (archiverColumns includes:(col id asSymbol)) ifTrue:[
+            newColumns add:col.
+        ].
+    ].
+    self tableColumns value:newColumns.
+    self columnDescriptors:(self tableColumns value).
+!
+
+stopProcess
+
+    |task|
+
+    terminateByMe := true.
+    (task := process) notNil ifTrue:[
+        process := nil.
+
+        Object errorSignal handle:[:ex|
+            Dialog warn:ex description.
+        ]do:[
+            task isDead ifFalse:[
+                task terminateWithAllSubprocesses.
+                task waitUntilTerminated.
+            ]
+        ]
+    ].
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication methodsFor:'command helper'!
+
+selectDirectoryDialog
+
+    | dir directory haveDirectory|
+
+    directory := self fileName directory.
+    haveDirectory := false.
+    [haveDirectory] whileFalse:[
+        dir := Dialog requestDirectoryName:'Which directory ?' default:dir.
+        dir isEmpty ifTrue:[ ^ self].
+        dir := dir asFilename.
+        (dir isExecutable not or:[dir isWritable not]) ifTrue:[
+            Dialog warn:'cant write to: ', dir asString.
+        ].
+        haveDirectory := true.
+    ].
+    ^ dir
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication methodsFor:'commands add'!
+
+addFilesToArchiv:colOfFiles
+
+
+    self archiver outStream:nil errorStream:(self getErrorStream) synchron:true.
+    self makeProcessFor:[
+        self archiver addFilesToArchiv:colOfFiles.
+    ] with:'add Files to archiv'.
+    (self archiver class == Archiver zipArchive) ifTrue:[
+        self listAllFilesFromArchiv.
+    ] ifFalse:[
+        self listFilesFromArchiv:colOfFiles.
+    ].
+    ^ true.
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication methodsFor:'commands extract'!
+
+extractAll
+
+    self extractSelectedFilesTo:nil withSelection:#all
+!
+
+extractSelectedFilesTo:aDirectory askForExtractOptions:askForExtractOptionsBoolean
+
+    self extractSelectedFilesTo:aDirectory withSelection:#selection askForExtractOptions:askForExtractOptionsBoolean
+!
+
+extractSelectedFilesTo:aDirectory withSelection:selectOrAll
+
+    self extractSelectedFilesTo:aDirectory withSelection:selectOrAll askForExtractOptions:true.
+!
+
+extractSelectedFilesTo:aDirectory withSelection:selectOrAll askForExtractOptions:askForExtractOptionsBoolean
+
+    | dir|
+
+    aDirectory isNil ifTrue:[
+        dir := self selectDirectoryDialog.
+        dir isNil ifTrue:[^ self].
+    ] ifFalse:[
+        dir := aDirectory.
+    ].
+    selectOrAll == #all ifTrue:[
+       self extractAllTo:dir.
+    ].
+    selectOrAll == #selection ifTrue:[
+        self extractSelectionTo:dir askForExtractOptions:askForExtractOptionsBoolean
+    ].
+    self updateFileBrowserIfPresentWith:dir.
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication methodsFor:'commands extract private'!
+
+extractAllTo:aDirectory 
+
+    self archiver outStream:nil errorStream:(self getErrorStream) synchron:true.
+    self makeProcessFor:[
+        self archiver extractTo:aDirectory.
+    ] with:'extract all files'.
+    ^ true.
+!
+
+extractSelectionTo:aDirectory askForExtractOptions:askForExtractOptionsBoolean
+
+    |  sel index extractWithDirectoryPart extractAllFilesInSelectedDirectories extractFiles|
+
+    extractWithDirectoryPart := true.
+    extractAllFilesInSelectedDirectories := false.
+    sel := self selectionHolder value.
+    (sel isNil or:[sel isEmpty]) ifTrue:[
+        sel := self archiveFileList value.
+    ].
+    sel := sel do:[:item|
+        item fileName: item fileName
+    ].
+    (askForExtractOptionsBoolean and:[self archiver class ~= Archiver zipArchive]) ifTrue:[
+        extractFiles := self selRemoveFilesForDirs:sel.
+    ] ifFalse:[
+        extractFiles := sel.
+    ].
+    
+    askForExtractOptionsBoolean ifTrue:[
+        index := extractFiles findFirst:[: el | el hasDirectoryPart].
+        index ~= 0 ifTrue:[
+            extractWithDirectoryPart := (Dialog confirmWithCancel:'Extract with directory part?' default:true).
+            extractWithDirectoryPart isNil ifTrue:[^ false].
+        ].
+    ].
+    extractWithDirectoryPart ifTrue:[
+        self extractWithDirectoryPartTo:aDirectory with:extractFiles.
+    ] ifFalse:[
+        self extractWithOutDirectoryPartTo:aDirectory with:extractFiles.
+    ].
+    ^ true
+!
+
+extractWithDirectoryPartTo:aDirectory with:extractFiles
+
+    self archiver outStream:nil errorStream:(self getErrorStream) synchron:true.
+    self makeProcessFor:[
+        self archiver extractTo:aDirectory with:extractFiles.
+    ] with:('extract Files to ', aDirectory asString).
+    ^ true.
+!
+
+extractWithOutDirectoryPartTo:aDirectory with:extractFiles
+
+    self archiver outStream:nil errorStream:(self getErrorStream) synchron:true.
+    self makeProcessFor:[
+        self archiver extractWithOutDirectoryTo:aDirectory 
+                      with:(extractFiles collect:[:item| item fileName]).
+    ] with:('extract Files to ', aDirectory asString).
+    ^ true.
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication methodsFor:'commands list'!
+
+listAllFilesFromArchiv
+
+    self archiveFileList value removeAll.
+    self listFilesFromArchiv:nil
+!
+
+listFilesFromArchiv:newColOfFiles
+
+    process notNil ifTrue:[
+        process waitUntilTerminated.
+    ].
+    self archiver outStream:(self getOutStream) errorStream:(self getErrorStream) synchron:true.
+    self makeProcessFor:[
+        self archiver listFilesFromArchiv:newColOfFiles.
+    ] with:'list Files'.
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication methodsFor:'commands remove'!
+
+removeFilesFromArchiv
+
+    | sel realSel list firtsPre stringCol stringRealSel|
+
+    sel := self selectionHolder value.
+    stringCol := sel collect:[: item| item fileName].
+    firtsPre := stringCol at:1.
+    stringCol from:2 do:[:el|
+         firtsPre :=  firtsPre commonPrefixWith:el.
+    ].
+    list := self archiveFileList value.
+    realSel := OrderedCollection new.
+    list do:[:item|
+        ((item fileName) startsWith:firtsPre) ifTrue:[
+            realSel add:item.
+        ].
+    ].
+    stringRealSel := realSel collect:[: item| item fileName].
+
+    self archiver outStream:nil errorStream:(self getErrorStream) synchron:true.
+    self makeProcessFor:[
+        self archiver removeFilesFromArchiv:stringCol.
+    ] with:'remove files'.
+
+    self archiveFileList value removeAll:realSel
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication methodsFor:'drag & drop'!
+
+canDrop:aContext argument:arg2 
+
+
+    |arg |
+    archiver class canAddFiles ifFalse:[^ false].
+    arg := aContext dropSource argument.
+    (arg == #browser or:[arg == #directoryTreeBrowser]) ifTrue:[
+        ^ true
+    ].
+    ^ false.
+!
+
+doDrop:aContext
+
+    |col source arg objects|
+
+    source := aContext dropSource.
+    arg := source argument.
+    objects := aContext dropObjects.
+    col := OrderedCollection new.
+    objects do:[:obj|
+        col add:(obj theObject).
+    ].
+    ^ self addFilesToArchiv:col.
+!
+
+doDrop:aContext argument:arg2 
+
+    | aBoolean |
+
+    aBoolean := self doDrop:aContext.
+    ^ aBoolean.
+!
+
+doStartDrag:aDropSource in:aView
+    "set the cursors before starting the drag & drop operation
+    "
+    |hdl sel|
+
+    archiver class canRemoveFiles ifFalse:[^ self].
+    sel := self selectionHolder value.
+
+    hdl := DragAndDropManager new.
+
+    hdl disabledCursor:self class DisabledCursorImage.
+    hdl enabledCursor:self class EnabledCursorImage.
+    hdl alienCursor:nil.
+
+    hdl startDragFrom:aView dropSource:aDropSource offset:#topLeft
+!
+
+getDisplayObjects:anArgument
+
+    | sel string size fnName stream|
+    sel := self selectionHolder value.
+    size := sel size.
+    size == 0  ifTrue:[^ ''].
+    stream := WriteStream on:''.
+    stream nextPutAll:(sel first fileName asFilename baseName asString).
+    size == 1 ifTrue:[
+        fnName := 'ui_menuitem.xpm'.
+    ] ifFalse:[
+        fnName := 'ui_submenu_open.xpm'.
+        stream nextPutAll:' ... '.
+        stream nextPutAll:(sel last fileName asFilename baseName asString).
+    ].
+    string := stream contents.
+    stream close.
+    ^ Array with:(LabelAndIcon icon:(Image fromFile:fnName)
+                             string:(Text string:string emphasis:#bold)
+                 )
+!
+
+getDropObjects:anArgument
+
+    | sel ret|
+    sel := self selectionHolder value.
+    ret := sel collect:[:el| 
+        DropObject new:(el fileName)
+    ].
+    ^ ret
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication methodsFor:'event handling'!
+
+processEvent:anEvent
+    "filter keyboard events.
+     Return true, if I have eaten the event"
+
+    |focusView key rawKey|
+
+    anEvent isKeyPressEvent ifTrue:[
+        focusView := anEvent targetView.
+        key := anEvent key.
+        rawKey := anEvent rawKey.
+
+        (focusView isSameOrComponentOf:self window) ifTrue:[
+"/            (key ~= #'Alt_L') ifTrue:[self halt.].
+            (key == #Delete) ifTrue:[
+                self removeFilesFromArchiv.
+                ^ true
+            ].
+        ]
+    ].
+    ^ false
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication methodsFor:'initialization & release'!
+
+postBuildFileTable:aWidget
+
+    fileTable := aWidget scrolledView.
+    fileTable wantsFocusWithPointerEnter.
+"/    FileBrowser icons keysAndValuesDo:[:aKey :anIcon|
+"/        fileTable registerImage:anIcon key:aKey.
+"/    ].
+    self columnDescriptors:(self class tableColumns).
+!
+
+postOpenWith:aBuilder
+
+    | currentDir contents suffix fileName file archivItem|
+
+    self windowGroup addPreEventHook:self.
+    self masterApplication isNil ifTrue:[
+        self masterApplication:nil.
+        currentDir := Filename homeDirectory.
+        contents := currentDir directoryContents.
+        fileName := contents detect:[: file |
+            suffix := file asFilename suffix asLowercase.
+            suffix = 'tgz'
+        ] ifNone:[nil].
+        fileName isNil ifTrue:[ 
+            Dialog warn:'cant find a Zip file in ', currentDir asString.
+            ^ self
+        ].
+        file := currentDir construct:fileName.
+        archivItem := DirectoryContentsBrowser itemClass with:file.
+        (self item:archivItem) ifFalse:[
+            Dialog warn:'file type of ', item fileName asString, ' not supported'.
+            ^ self.
+        ].
+    ].
+    self listAllFilesFromArchiv.
+    ^ super postOpenWith:aBuilder.
+!
+
+release
+
+    self archiver release.
+    ^ super release.
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication methodsFor:'queries'!
+
+archivType
+
+    | file firstsuffix secondsuffix|
+
+    file := self fileName.
+    firstsuffix := file withoutSuffix suffix.
+    secondsuffix := file suffix.
+    (secondsuffix = 'tgz' or:[firstsuffix = 'tar' and:[secondsuffix = 'gz']]) ifTrue:[
+        ^ #tarFileCompressed
+    ].
+    (secondsuffix = 'tar') ifTrue:[
+        ^ #tarFile
+    ].
+    (secondsuffix = 'gz') ifTrue:[
+        ^ #gzipFile
+    ].
+    (secondsuffix = 'zip') ifTrue:[
+        ^ #zipFile
+    ].
+!
+
+canDelete
+
+    ^ (self hasOneSelectionInList and:[archiver class canRemoveFiles])
+!
+
+selRemoveFilesForDirs:aSel
+
+    |stringCol newSel string|
+
+    stringCol := (aSel collect:[: item| item fileName]).
+    newSel := aSel copy.
+    aSel do:[:item |
+        item isDirectory ifTrue:[
+            string := item fileName.
+            stringCol doWithIndex:[:filename : index|
+                (filename ~= string and:[filename startsWith:string]) ifTrue:[
+                    newSel remove:(aSel at:index) ifAbsent:[nil].
+                ]
+            ]
+        ].
+    ].
+    ^ newSel.
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication methodsFor:'sorting'!
+
+generateSortBlock:instanceName
+
+    | aSymbol cmpOp sortCaselessLocal|
+
+    aSymbol := instanceName asSymbol.
+    sortCaselessLocal := self sortCaseless value.
+    currentSortOrder isNil ifTrue:[
+        currentSortOrder := aSymbol.
+        currentSortOrder := Dictionary new.
+        currentSortOrder at:#column put:aSymbol.
+        currentSortOrder at:#reverse put:false.
+        currentSortOrder at:#sortCaseless put:sortCaselessLocal.
+    ] ifFalse:[
+        (currentSortOrder at:#column) = aSymbol ifTrue:[
+            "/ same column like before - change sort order
+            | isReverse |
+            isReverse := currentSortOrder at:#reverse.
+            currentSortOrder at:#reverse put:(isReverse not).
+        ] ifFalse:[
+            "/ another column - remark column
+            currentSortOrder at:#column put:aSymbol.
+        ]
+    ].
+    (currentSortOrder at:#reverse) ifTrue:[
+        cmpOp := #'>'
+    ] ifFalse:[
+        cmpOp := #'<'
+    ].
+    ^ [:a :b | 
+            |entry1 entry2|
+
+            entry1 := (a perform:aSymbol).
+            entry2 := (b perform:aSymbol).
+            aSymbol = #fileName ifTrue:[
+                sortCaselessLocal ifTrue:[
+                    entry1 := entry1 asString asLowercase.
+                    entry2 := entry2 asString asLowercase.
+                ] ifFalse:[
+                    entry1 := entry1 asString.
+                    entry2 := entry2 asString.
+                ].
+            ].
+            entry1 perform:cmpOp with:entry2
+    ].
+!
+
+sortList:instanceName 
+
+
+    |sortBlock fileList sortCol|
+
+    sortBlock := self generateSortBlock:instanceName.
+    fileList := self archiveFileList value.
+    sortCol := SortedCollection sortBlock:sortBlock.
+    sortCol addAll:fileList.
+    fileList removeAll.
+    fileList addAll:sortCol.
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication::ArchivItem methodsFor:'accessing'!
+
+compressSize
+    "return the value of the instance variable 'compressSize' (automatically generated)"
+
+    ^ compressSize
+!
+
+compressSize:something
+    "set the value of the instance variable 'compressSize' (automatically generated)"
+
+    compressSize := something.
+!
+
+crc
+    "return the value of the instance variable 'crc' (automatically generated)"
+
+    ^ crc
+!
+
+crc:something
+    "set the value of the instance variable 'crc' (automatically generated)"
+
+    crc := something.
+!
+
+dateAndTime
+    "return the value of the instance variable 'dateAndTime' (automatically generated)"
+
+    ^ dateAndTime
+!
+
+dateAndTime:something
+    "set the value of the instance variable 'dateAndTime' (automatically generated)"
+
+    dateAndTime := something.
+!
+
+fileName
+    "return the value of the instance variable 'fileName' (automatically generated)"
+
+    ^ fileName
+!
+
+fileName:something
+    "set the value of the instance variable 'fileName' (automatically generated)"
+
+    fileName := something withoutSpaces.
+!
+
+icon
+    "return the value of the instance variable 'icon' (automatically generated)"
+
+    ^ icon
+!
+
+icon:something
+    "set the value of the instance variable 'icon' (automatically generated)"
+
+    icon := something.
+!
+
+isDirectory
+    "return the value of the instance variable 'directory' (automatically generated)"
+
+    ^ isDirectory
+!
+
+isDirectory:something
+    "set the value of the instance variable 'isDirectory' (automatically generated)"
+
+    isDirectory := something.
+!
+
+method
+    "return the value of the instance variable 'method' (automatically generated)"
+
+    ^ method
+!
+
+method:something
+    "set the value of the instance variable 'method' (automatically generated)"
+
+    method := something.
+!
+
+ownerGroup
+    "return the value of the instance variable 'owner' (automatically generated)"
+
+    ^ ownerGroup
+!
+
+ownerGroup:something
+    "set the value of the instance variable 'owner' (automatically generated)"
+
+    ownerGroup := something.
+!
+
+permissions
+    "return the value of the instance variable 'permissions' (automatically generated)"
+
+    ^ permissions
+!
+
+permissions:something
+    "set the value of the instance variable 'permissions' (automatically generated)"
+
+    permissions := something.
+!
+
+ratio
+    "return the value of the instance variable 'ratio' (automatically generated)"
+
+    ^ ratio
+!
+
+ratio:something
+    "set the value of the instance variable 'ratio' (automatically generated)"
+
+    ratio := something.
+!
+
+size
+    "return the value of the instance variable 'size' (automatically generated)"
+
+    ^ size
+!
+
+size:something
+    "set the value of the instance variable 'size' (automatically generated)"
+
+    size := something.
+!
+
+sizeAsNumber
+    "return the value of the instance variable 'size' (automatically generated)"
+
+    ^ size asInteger
+!
+
+type
+    "return the value of the instance variable 'type' (automatically generated)"
+
+    ^ type
+!
+
+type:something
+    "set the value of the instance variable 'type' (automatically generated)"
+
+    type := something.
+!
+
+version
+    "return the value of the instance variable 'version' (automatically generated)"
+
+    ^ version
+!
+
+version:something
+    "set the value of the instance variable 'version' (automatically generated)"
+
+    version := something.
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication::ArchivItem methodsFor:'printing'!
+
+printString
+
+    ^ self fileName asString
+! !
+
+!FileApplicationNoteBook::ArchiveViewApplication::ArchivItem methodsFor:'queries'!
+
+hasDirectoryPart
+
+    ^ self fileName asFilename components size ~= 1
+! !
+
+!FileApplicationNoteBook::CommandResult class methodsFor:'defaults'!
+
+tabStringFor:aApplicationType
+
+    ^ 'Execution result'
+!
+
+wantNewApplicationAnyway
+
+    ^ false
+! !
+
+!FileApplicationNoteBook::CommandResult class methodsFor:'interface specs'!
+
+windowSpec
+    "This resource specification was automatically generated
+     by the UIPainter of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the UIPainter may not be able to read the specification."
+
+    "
+     UIPainter new openOnClass:NoteBookApplication::CommandResult andSelector:#windowSpec
+     NoteBookApplication::CommandResult new openInterface:#windowSpec
+     NoteBookApplication::CommandResult open
+    "
+
+    <resource: #canvas>
+
+    ^ 
+     #(#FullSpec
+        #name: #windowSpec
+        #window: 
+       #(#WindowSpec
+          #label: 'NoteBookApplication::CommandResult'
+          #name: 'NoteBookApplication::CommandResult'
+          #min: #(#Point 10 10)
+          #max: #(#Point 1024 768)
+          #bounds: #(#Rectangle 16 42 519 395)
+          #menu: #mainMenu
+        )
+        #component: 
+       #(#SpecCollection
+          #collection: #(
+           #(#MenuPanelSpec
+              #name: 'ToolBar1'
+              #layout: #(#LayoutFrame 0 0.0 0 0 0 1.0 32 0)
+              #menu: #menu
+              #textDefault: true
+            )
+           #(#ArbitraryComponentSpec
+              #name: 'ArbitraryComponent1'
+              #layout: #(#LayoutFrame 0 0.0 32 0 0 1.0 0 1)
+              #hasHorizontalScrollBar: true
+              #hasVerticalScrollBar: true
+              #hasBorder: false
+              #component: #TextCollector
+              #postBuildCallback: #postBuildTextCollector:
+            )
+           #(#LabelSpec
+              #label: 'FileLabel'
+              #name: 'FileLabel'
+              #layout: #(#LayoutFrame 87 0 2 0 -36 1 30 0)
+              #level: -1
+              #translateLabel: true
+              #labelChannel: #labelHolder
+              #adjust: #left
+            )
+           )
+         
+        )
+      )
+! !
+
+!FileApplicationNoteBook::CommandResult class methodsFor:'menu specs'!
+
+menu
+    "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:FileApplicationNoteBook::CommandResult andSelector:#menu
+     (Menu new fromLiteralArrayEncoding:(FileApplicationNoteBook::CommandResult menu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #label: 'Stop'
+            #translateLabel: true
+            #isButton: true
+            #nameKey: #Stop
+            #value: #doStopProcess
+            #enabled: #enableStopButton
+            #labelImage: #(#ResourceRetriever #ToolbarIconLibrary #stop22x22Icon 'Stop')
+          )
+         #(#MenuItem
+            #label: 'Close'
+            #translateLabel: true
+            #isButton: true
+            #nameKey: #Close
+            #isVisible: #isEmbeddedApplication
+            #startGroup: #right
+            #value: #doClose
+            #labelImage: #(#ResourceRetriever #AbstractFileBrowser #closeIcon)
+          )
+         )
+        nil
+        nil
+      )
+! !
+
+!FileApplicationNoteBook::CommandResult methodsFor:'accessing'!
+
+resultStream
+    "return the value of the instance variable 'resultStream' (automatically generated)"
+
+    ^ resultStream
+!
+
+resultStream:something
+    "set the value of the instance variable 'resultStream' (automatically generated)"
+
+    resultStream := something.
+! !
+
+!FileApplicationNoteBook::CommandResult methodsFor:'actions'!
+
+changeTabTo:aString 
+
+    | masterApplication |
+
+    self labelHolder value:aString.
+    masterApplication := self masterApplication.
+    masterApplication isNil ifFalse:[
+        masterApplication tabStringChangeTo:aString for:self.
+    ].
+!
+
+doStopProcess
+
+    | myProcess |
+
+    myProcess := self process value.
+    myProcess notNil ifTrue:[
+        self notifyChannel value:('kill ', myProcess name).
+        myProcess terminate.    
+        self backgroundProcesses remove:myProcess ifAbsent:[].
+    ].
+! !
+
+!FileApplicationNoteBook::CommandResult methodsFor:'aspects'!
+
+enableStopButton
+
+    enableStopButton isNil ifTrue:[
+        enableStopButton := false asValue.
+    ].
+    ^ enableStopButton
+!
+
+labelHolder
+
+    labelHolder isNil ifTrue:[
+        labelHolder := '' asValue.
+    ].
+    ^ labelHolder.
+!
+
+process
+    "return/create the 'process' value holder (automatically generated)"
+
+    process isNil ifTrue:[
+        process := ValueHolder new.
+        process addDependent:self.
+    ].
+    ^ process
+! !
+
+!FileApplicationNoteBook::CommandResult methodsFor:'change & update'!
+
+update:something with:aParameter from:changedObject
+    "Invoked when an object that I depend upon sends a change notification."
+
+    "stub code automatically generated - please change as required"
+
+    changedObject == self process ifTrue:[
+        self enableStopButton value:changedObject value notNil.
+        ^ self
+    ].
+    super update:something with:aParameter from:changedObject
+! !
+
+!FileApplicationNoteBook::CommandResult methodsFor:'initialization & release'!
+
+postBuildTextCollector:aBuilder
+
+    self resultStream:aBuilder scrolledView.
+!
+
+postBuildWith:aBuilder
+    "This is a hook method generated by the Browser.
+     It will be invoked during the initialization of your app/dialog,
+     after all of the visual components have been built, 
+     but BEFORE the top window is made visible.
+     Add any app-specific actions here (reading files, setting up values etc.)
+     See also #postOpenWith:, which is invoked after opening."
+
+    "/ add any code here ...
+
+    ^ super postBuildWith:aBuilder
+!
+
+postOpenWith:aBuilder
+    "This is a hook method generated by the Browser.
+     It will be invoked right after the applications window has been opened.
+     Add any app-specific actions here (starting background processes etc.).
+     See also #postBuildWith:, which is invoked before opening."
+
+    "/ add any code here ...
+
+    self masterApplication isNil ifTrue:[
+        self masterApplication:nil.
+    ].
+    ^ super postOpenWith:aBuilder
+!
+
+release
+
+    self doStopProcess.
+    ^ super release
+! !
+
+!FileApplicationNoteBook::CommandResult methodsFor:'printing'!
+
+printString
+
+    ^ 'CommandResult Application'
+! !
+
+!FileApplicationNoteBook::HtmlViewApplication class methodsFor:'defaults'!
+
+tabStringFor:aApplicationType
+
+    ^ 'HTML View for:'
+! !
+
+!FileApplicationNoteBook::HtmlViewApplication class methodsFor:'interface specs'!
+
+windowSpec
+    "This resource specification was automatically generated
+     by the UIPainter of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the UIPainter may not be able to read the specification."
+
+    "
+     UIPainter new openOnClass:NoteBookApplication::HtmlViewApplication andSelector:#windowSpec
+     NoteBookApplication::HtmlViewApplication new openInterface:#windowSpec
+     NoteBookApplication::HtmlViewApplication open
+    "
+
+    <resource: #canvas>
+
+    ^ 
+     #(#FullSpec
+        #name: #windowSpec
+        #window: 
+       #(#WindowSpec
+          #label: 'NoteBookApplication::HtmlView'
+          #name: 'NoteBookApplication::HtmlView'
+          #min: #(#Point 10 10)
+          #max: #(#Point 1024 768)
+          #bounds: #(#Rectangle 16 42 692 534)
+          #menu: #mainMenu
+        )
+        #component: 
+       #(#SpecCollection
+          #collection: #(
+           #(#MenuPanelSpec
+              #name: 'MenuHtml'
+              #layout: #(#LayoutFrame 0 0.0 0 0 0 1.0 32 0)
+              #visibilityChannel: #isEmbeddedApplication
+              #menu: #menu
+              #textDefault: true
+            )
+           #(#ArbitraryComponentSpec
+              #name: 'HTMLView'
+              #layout: #(#LayoutFrame 0 0.0 32 0.0 0 1.0 0 1)
+              #hasHorizontalScrollBar: true
+              #hasVerticalScrollBar: true
+              #miniScrollerHorizontal: false
+              #miniScrollerVertical: false
+              #hasBorder: false
+              #component: #HTMLDocumentView
+              #postBuildCallback: #postBuildHtmlView:
+            )
+           #(#LabelSpec
+              #label: 'FileLabel'
+              #name: 'FileLabel'
+              #layout: #(#LayoutFrame 212 0 2 0 -73 1 30 0)
+              #level: -1
+              #translateLabel: true
+              #labelChannel: #labelHolder
+              #adjust: #left
+            )
+           )
+         
+        )
+      )
+! !
+
+!FileApplicationNoteBook::HtmlViewApplication class methodsFor:'menu specs'!
+
+menu
+    "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:FileApplicationNoteBook::HtmlViewApplication andSelector:#menu
+     (Menu new fromLiteralArrayEncoding:(FileApplicationNoteBook::HtmlViewApplication menu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #label: 'Reload'
+            #translateLabel: true
+            #isButton: true
+            #value: #doReload
+            #labelImage: #(#ResourceRetriever nil #htmlReloadIcon)
+          )
+         #(#MenuItem
+            #label: 'Back'
+            #translateLabel: true
+            #isButton: true
+            #value: #doGoBack
+            #labelImage: #(#ResourceRetriever #Icon #leftIcon)
+          )
+         #(#MenuItem
+            #label: 'Print'
+            #translateLabel: true
+            #isButton: true
+            #value: #doPrint
+            #labelImage: #(#ResourceRetriever #ToolbarIconLibrary #printer22x22Icon)
+          )
+         #(#MenuItem
+            #label: 'Close'
+            #translateLabel: true
+            #isButton: true
+            #hideMenuOnActivated: false
+            #startGroup: #right
+            #value: #doClose
+            #labelImage: #(#ResourceRetriever #AbstractFileBrowser #closeIcon)
+          )
+         )
+        nil
+        nil
+      )
+! !
+
+!FileApplicationNoteBook::HtmlViewApplication class methodsFor:'queries'!
+
+canOpenItem:aItem
+
+    ^ (aItem hasMimeType and:[aItem mimeType isHtml])
+!
+
+wantNewApplicationAnyway
+
+    ^ false
+! !
+
+!FileApplicationNoteBook::HtmlViewApplication methodsFor:'accessing'!
+
+htmlView
+    "return the value of the instance variable 'imageView' (automatically generated)"
+
+    ^ htmlView
+!
+
+htmlView:something
+    "set the value of the instance variable 'imageView' (automatically generated)"
+
+    htmlView := something.
+!
+
+item:aItem 
+
+    |retVal|
+
+    self labelHolder value:aItem fileName asString.
+    retVal := super item:aItem.
+    self setupHtmlView.
+    ^ retVal
+! !
+
+!FileApplicationNoteBook::HtmlViewApplication methodsFor:'actions'!
+
+doGoBack
+
+    self htmlView menu_back.
+!
+
+doGoHome
+
+    self htmlView menu_home.
+!
+
+doHelp
+
+    self htmlView menu_help.
+!
+
+doPrint
+
+    self htmlView menu_print.
+!
+
+doReload
+
+    self htmlView menu_reload.
+!
+
+setupHtmlView
+
+    | html file directory|
+
+    html := self htmlView.
+    html isNil ifTrue:[^ self].
+    file := self fileName.
+    directory := file directoryName.
+    html homeDocument:(file asString).
+    html setTopDirectoryName:directory.
+    html uriHolder:self labelHolder.
+    html infoHolder:self notifyChannel.
+    html linkButtonPanel:nil.
+    ^ html
+! !
+
+!FileApplicationNoteBook::HtmlViewApplication methodsFor:'aspects'!
+
+labelHolder
+
+    labelHolder isNil ifTrue:[
+        labelHolder := '' asValue.
+    ].
+    ^ labelHolder.
+! !
+
+!FileApplicationNoteBook::HtmlViewApplication methodsFor:'initialization & release'!
+
+postBuildHtmlView:aWidget
+
+    self htmlView: aWidget scrolledView.
+    self htmlView wantsFocusWithPointerEnter.
+!
+
+postOpenWith:aBuilder 
+    "
+    only invoked if the application not started from a master
+    "
+
+    |currentDir contents suffix fileName|
+
+    self masterApplication isNil ifTrue:[
+        self masterApplication:nil.
+        currentDir := Filename homeDirectory.
+
+        contents := currentDir directoryContents.
+        fileName := contents 
+                    detect:[:file | 
+                        suffix := file asFilename suffix asLowercase.
+                        suffix = 'html'
+                    ]
+                    ifNone:[nil].
+        fileName isNil ifTrue:[
+            Dialog warn:'cant find a HTML file in ' , currentDir asString.
+            ^ self
+        ].
+        self item:(DirectoryContentsBrowser itemClass with:('../../doc/online/english/TOP.html' asFilename)).
+    ].
+    self setupHtmlView.
+    ^ super postOpenWith:aBuilder
+! !
+
+!FileApplicationNoteBook::ImageViewApplication class methodsFor:'defaults'!
+
+tabStringFor:aApplicationType
+
+    ^ 'Image for:'
+! !
+
+!FileApplicationNoteBook::ImageViewApplication class methodsFor:'image specs'!
+
+fitSize20x20Icon
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self fitSize20x20Icon inspect
+     ImageEditor openOnClass:self andSelector:#fitSize20x20Icon
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'FileApplicationNoteBook::ImageViewApplication class fitSize20x20Icon'
+        ifAbsentPut:[(Depth4Image new) width: 20; height: 20; photometric:(#palette); bitsPerSample:(#(4 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+@@DQDQDQDQDP@@@PDQDQDQDQ@P@A@ADQDQDQDP@PD@@PDQDQDPD@@QDQ@ADQDQ@@DQDQD@@@@@@@@@DQDQDPQDQDQ@DQDQDQDDQUUTPADQDQDQAEUUUT@QDQ
+DQDPQEUUQ@DQDQDQDDQFQDPADQDQDQADQ$QD@QDQDQDPL3X3Q@DQDQDQDCL3L3LADQDQD@@@@@@@@@DQDQD@DQDQDP@QDQ@@DADQDQDA@@DA@ADQDQDQDP@P
+@@@QDQDQDQDA@@@ADQDQDQDQD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; colorMapFromArray:#[0 0 0 255 255 255 0 0 0 0 137 0 174 218 230 0 206 0 133 60 36]; mask:((Depth1Image new) width: 20; height: 20; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+8@A00@@0(@APE@J@C@L@G?>@A?8@A?8@A?8@A?8@A?8@A?8@A?8@A?8@G?>@C@L@E@J@(@AP0@@08@A0@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; yourself); yourself]
+! !
+
+!FileApplicationNoteBook::ImageViewApplication class methodsFor:'interface specs'!
+
+windowSpec
+    "This resource specification was automatically generated
+     by the UIPainter of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the UIPainter may not be able to read the specification."
+
+    "
+     UIPainter new openOnClass:FileApplicationNoteBook::ImageViewApplication andSelector:#windowSpec
+     FileApplicationNoteBook::ImageViewApplication new openInterface:#windowSpec
+     FileApplicationNoteBook::ImageViewApplication open
+    "
+
+    <resource: #canvas>
+
+    ^ 
+     #(#FullSpec
+        #name: #windowSpec
+        #window: 
+       #(#WindowSpec
+          #label: 'ImageViewer'
+          #name: 'ImageViewer'
+          #min: #(#Point 10 10)
+          #max: #(#Point 1024 768)
+          #bounds: #(#Rectangle 16 42 692 534)
+          #menu: #mainMenu
+        )
+        #component: 
+       #(#SpecCollection
+          #collection: #(
+           #(#MenuPanelSpec
+              #name: 'MenuTerminal'
+              #layout: #(#LayoutFrame 0 0.0 0 0 0 1.0 32 0)
+              #visibilityChannel: #isEmbeddedApplication
+              #menu: #menu
+              #textDefault: true
+            )
+           #(#ArbitraryComponentSpec
+              #name: 'TerminalView'
+              #layout: #(#LayoutFrame 0 0.0 32 0.0 0 1.0 0 1.0)
+              #hasHorizontalScrollBar: true
+              #hasVerticalScrollBar: true
+              #miniScrollerHorizontal: false
+              #miniScrollerVertical: false
+              #hasBorder: false
+              #component: #ImageView
+              #postBuildCallback: #postBuildImageView:
+            )
+           )
+         
+        )
+      )
+! !
+
+!FileApplicationNoteBook::ImageViewApplication class methodsFor:'menu specs'!
+
+menu
+    "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:FileApplicationNoteBook::ImageViewApplication andSelector:#menu
+     (Menu new fromLiteralArrayEncoding:(FileApplicationNoteBook::ImageViewApplication menu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #label: 'Edit'
+            #translateLabel: true
+            #isButton: true
+            #nameKey: #EditImage
+            #value: #editImage
+          )
+         #(#MenuItem
+            #label: '-'
+          )
+         #(#MenuItem
+            #label: 'FitSize'
+            #translateLabel: true
+            #isButton: true
+            #triggerOnDown: true
+            #labelImage: #(#ResourceRetriever #'FileApplicationNoteBook::ImageViewApplication' #fitSize20x20Icon)
+            #indication: #fitSize
+          )
+         #(#MenuItem
+            #label: '-'
+          )
+         #(#MenuItem
+            #label: 'Close'
+            #translateLabel: true
+            #isButton: true
+            #hideMenuOnActivated: false
+            #startGroup: #right
+            #value: #doClose
+            #labelImage: #(#ResourceRetriever #AbstractFileBrowser #closeIcon)
+          )
+         )
+        nil
+        nil
+      )
+! !
+
+!FileApplicationNoteBook::ImageViewApplication class methodsFor:'queries'!
+
+canOpenItem:aItem
+
+    ^ (aItem hasMimeType and:[aItem mimeType isImage])
+!
+
+wantNewApplicationAnyway
+
+    ^ false
+! !
+
+!FileApplicationNoteBook::ImageViewApplication methodsFor:'accessing'!
+
+image:something
+    "set the value of the instance variable 'image' (automatically generated)"
+
+    image := something.
+!
+
+imageView
+    "return the value of the instance variable 'imageView' (automatically generated)"
+
+    ^ imageView
+!
+
+imageView:something
+    "set the value of the instance variable 'imageView' (automatically generated)"
+
+    imageView := something.
+! !
+
+!FileApplicationNoteBook::ImageViewApplication methodsFor:'actions'!
+
+changeItem:aItem
+
+    self item:aItem.
+    self setupImageView.
+    ^ true
+!
+
+editImage
+    |img|
+
+    img := self image.
+    img notNil ifTrue:[
+        img edit.
+    ].
+!
+
+image
+    |img fn e|
+
+    fn := self fileName.
+    img := Image fromFile:fn.
+    img isNil ifTrue:[
+        fn exists ifTrue:[
+            e := 'Unknown/unsupported image format'
+        ] ifFalse:[
+            e := 'No such image'
+        ].
+        Dialog warn:e.
+        ^ nil
+    ].
+    ^ img.
+!
+
+setupImageView
+    |img|
+
+    self window topView withWaitCursorDo:[
+        img := self image.
+        img notNil ifTrue:[
+            self image:img.
+            imageView image:img
+        ]
+    ]
+! !
+
+!FileApplicationNoteBook::ImageViewApplication methodsFor:'aspects'!
+
+fitSize
+    "return/create the 'fitSize' value holder (automatically generated)"
+
+    fitSize isNil ifTrue:[
+        fitSize := ValueHolder new.
+        fitSize addDependent:self.
+    ].
+    ^ fitSize
+! !
+
+!FileApplicationNoteBook::ImageViewApplication methodsFor:'change & update'!
+
+update:something with:aParameter from:changedObject
+    changedObject == self fitSize ifTrue:[
+        changedObject value ifTrue:[
+            imageView adjust:#fitBig.
+        ] ifFalse:[
+            imageView adjust:nil.
+        ].
+        ^ self
+    ].
+    super update:something with:aParameter from:changedObject
+! !
+
+!FileApplicationNoteBook::ImageViewApplication methodsFor:'initialization & release'!
+
+postBuildImageView:aWidget
+
+    self imageView: aWidget scrolledView.
+    self imageView wantsFocusWithPointerEnter.
+!
+
+postOpenWith:aBuilder 
+    "
+    only invoked if the application not started from a master
+    "
+
+    |currentDir contents suffix fileName|
+
+    self masterApplication isNil ifTrue:[
+        self masterApplication:nil.
+        currentDir := Filename currentDirectory.
+        contents := currentDir directoryContents.
+        fileName := contents 
+                    detect:[:file | 
+                        suffix := file asFilename suffix asLowercase.
+                        Image isImageFileSuffix:suffix
+                    ]
+                    ifNone:[nil].
+        fileName isNil ifTrue:[
+            Dialog warn:'cant find a Image in ' , currentDir asString.
+            ^ self
+        ].
+        self item:(DirectoryContentsBrowser itemClass with:(currentDir construct:fileName))
+    ].
+    self setupImageView.
+    ^ super postOpenWith:aBuilder
+! !
+
+!FileApplicationNoteBook::Terminal class methodsFor:'defaults'!
+
+tabStringFor:aApplicationType
+
+    ^ 'Terminal in:'
+! !
+
+!FileApplicationNoteBook::Terminal class methodsFor:'interface specs'!
+
+windowSpec
+    "This resource specification was automatically generated
+     by the UIPainter of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the UIPainter may not be able to read the specification."
+
+    "
+     UIPainter new openOnClass:NoteBookApplication::Terminal andSelector:#windowSpec
+     NoteBookApplication::Terminal new openInterface:#windowSpec
+     NoteBookApplication::Terminal open
+    "
+
+    <resource: #canvas>
+
+    ^ 
+     #(#FullSpec
+        #name: #windowSpec
+        #window: 
+       #(#WindowSpec
+          #label: 'NoteBookApplication::Terminal'
+          #name: 'NoteBookApplication::Terminal'
+          #min: #(#Point 10 10)
+          #max: #(#Point 1024 768)
+          #bounds: #(#Rectangle 16 42 692 534)
+          #menu: #mainMenu
+        )
+        #component: 
+       #(#SpecCollection
+          #collection: #(
+           #(#MenuPanelSpec
+              #name: 'MenuTerminal'
+              #layout: #(#LayoutFrame 0 0.0 0 0 0 1.0 32 0)
+              #menu: #menu
+              #textDefault: true
+            )
+           #(#ArbitraryComponentSpec
+              #name: 'TerminalView'
+              #layout: #(#LayoutFrame 0 0.0 32 0.0 0 1.0 0 1.0)
+              #hasHorizontalScrollBar: true
+              #hasVerticalScrollBar: true
+              #miniScrollerHorizontal: false
+              #miniScrollerVertical: false
+              #hasBorder: false
+              #component: #terminalView
+            )
+           )
+         
+        )
+      )
+! !
+
+!FileApplicationNoteBook::Terminal class methodsFor:'menu specs'!
+
+menu
+    "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:FileApplicationNoteBook::Terminal andSelector:#menu
+     (Menu new fromLiteralArrayEncoding:(FileApplicationNoteBook::Terminal menu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #label: 'Save'
+            #translateLabel: true
+            #isButton: true
+            #nameKey: #Save
+            #value: #saveAs
+            #labelImage: #(#ResourceRetriever #ToolbarIconLibrary #saveToFile28x22Icon)
+          )
+         #(#MenuItem
+            #label: 'Close'
+            #translateLabel: true
+            #isButton: true
+            #hideMenuOnActivated: false
+            #isVisible: #isEmbeddedApplication
+            #startGroup: #right
+            #value: #doClose
+            #labelImage: #(#ResourceRetriever #AbstractFileBrowser #closeIcon)
+          )
+         )
+        nil
+        nil
+      )
+! !
+
+!FileApplicationNoteBook::Terminal methodsFor:'accessing'!
+
+terminalView
+
+    terminalView isNil ifTrue:[
+        terminalView := VT100TerminalView new.
+    ].
+    ^ terminalView.
+! !
+
+!FileApplicationNoteBook::Terminal methodsFor:'actions'!
+
+saveAs
+
+    self terminalView save.
+! !
+
+!FileApplicationNoteBook::Terminal methodsFor:'initialization & release'!
+
+postBuildWith:aBuilder
+
+    ^ super postBuildWith:aBuilder
+!
+
+shellFinished
+
+    | master text string|
+
+    master := self masterApplication.
+    master notNil ifTrue:[
+        string := ' - closed'.
+        master tabStringAdd:string for:self.
+    ].
+    self notifyChannel value:'shell in ' , self fileName asString, ' finished'.
+    terminalView cr.
+    text := '>> shell closed' asText allBold.
+    text colorizeAllWith:Color red.
+    terminalView nextPutAll:text.
+!
+
+startShell
+    |vt100|
+
+    vt100 := self terminalView.
+    vt100 shellTerminateAction:[ self shellFinished ].
+    vt100 startShellIn:(self fileName).
+! !
+
+!FileApplicationNoteBook::Terminal methodsFor:'printing'!
+
+printString
+
+    ^ ('Terminal on:', self fileName baseName)
+! !
+
+!FileApplicationNoteBook::Terminal methodsFor:'queries'!
+
+getTabStringEnd
+
+" get the tab string from the application list on the class side "
+
+    ^ '..', OperatingSystem fileSeparator, self fileName baseName, OperatingSystem fileSeparator
+! !
+
+!FileApplicationNoteBook::Terminal methodsFor:'startup & release'!
+
+postOpenWith:aBuilder
+
+    "
+    only invoked if the application not started from a master
+    "
+    self masterApplication isNil ifTrue:[
+        self masterApplication:nil.
+        self item:(DirectoryContentsBrowser itemClass with:(Filename currentDirectory asAbsoluteFilename)).
+    ].
+    self startShell.
+    ^ super postOpenWith:aBuilder.
+! !
+
+!FileApplicationNoteBook::TextEditor class methodsFor:'defaults'!
+
+tabStringFor:aApplicationType
+
+    aApplicationType == #directoryDescription ifTrue:[
+        ^ 'Directory description for:'
+    ] ifFalse:[
+        ^ 'Editor on:'
+    ].
+!
+
+wantNewApplicationAnyway
+
+    ^ false
+! !
+
+!FileApplicationNoteBook::TextEditor class methodsFor:'interface - specs'!
+
+windowSpec
+    "This resource specification was automatically generated
+     by the UIPainter of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the UIPainter may not be able to read the specification."
+
+    "
+     UIPainter new openOnClass:NoteBookApplication::TextEditor andSelector:#windowSpec
+     NoteBookApplication::TextEditor new openInterface:#windowSpec
+     NoteBookApplication::TextEditor open
+    "
+
+    <resource: #canvas>
+
+    ^ 
+     #(#FullSpec
+        #name: #windowSpec
+        #window: 
+       #(#WindowSpec
+          #label: 'TextEditor'
+          #name: 'TextEditor'
+          #min: #(#Point 10 10)
+          #max: #(#Point 1024 768)
+          #bounds: #(#Rectangle 12 22 662 322)
+        )
+        #component: 
+       #(#SpecCollection
+          #collection: #(
+           #(#MenuPanelSpec
+              #name: 'MenuTextEditor'
+              #layout: #(#LayoutFrame 0 0.0 0 0 0 1.0 32 0)
+              #menu: #menu
+              #textDefault: true
+            )
+           #(#TextEditorSpec
+              #name: 'TextEditor'
+              #layout: #(#LayoutFrame 0 0.0 32 0 0 1.0 0 1.0)
+              #model: #fileContentsModel
+              #hasHorizontalScrollBar: true
+              #hasVerticalScrollBar: true
+              #modifiedChannel: #modifiedChannel
+              #acceptCallBack: #accept
+              #postBuildCallback: #postBuildTextEditor:
+            )
+           )
+         
+        )
+      )
+! !
+
+!FileApplicationNoteBook::TextEditor class methodsFor:'menu specs'!
+
+menu
+    "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:FileApplicationNoteBook::TextEditor andSelector:#menu
+     (Menu new fromLiteralArrayEncoding:(FileApplicationNoteBook::TextEditor menu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #label: 'Save'
+            #translateLabel: true
+            #isButton: true
+            #nameKey: #Save
+            #value: #accept
+            #enabled: #enableSave
+            #labelImage: #(#ResourceRetriever #ToolbarIconLibrary #saveToFile28x22Icon)
+          )
+         #(#MenuItem
+            #label: 'Reload'
+            #translateLabel: true
+            #isButton: true
+            #nameKey: #Reload
+            #value: #reload
+            #enabled: #enableReload
+            #labelImage: #(#ResourceRetriever #ToolbarIconLibrary #reloadFromFile28x22Icon)
+          )
+         #(#MenuItem
+            #label: ''
+          )
+         #(#MenuItem
+            #label: 'Print'
+            #translateLabel: true
+            #isButton: true
+            #nameKey: #Print
+            #value: #doPrint
+            #enabled: #enableHexToggle
+            #labelImage: #(#ResourceRetriever #ToolbarIconLibrary #printer22x22Icon)
+          )
+         #(#MenuItem
+            #label: ''
+          )
+         #(#MenuItem
+            #label: 'Hex'
+            #translateLabel: true
+            #isButton: true
+            #enabled: #enableHexToggle
+            #labelImage: #(#ResourceRetriever #AbstractFileBrowser #hexToggle22x22Icon)
+            #indication: #printAsHexDump
+          )
+         #(#MenuItem
+            #label: 'Close'
+            #translateLabel: true
+            #isButton: true
+            #hideMenuOnActivated: false
+            #isVisible: #isEmbeddedApplication
+            #startGroup: #right
+            #value: #doClose
+            #labelImage: #(#ResourceRetriever #AbstractFileBrowser #closeIcon)
+          )
+         )
+        nil
+        nil
+      )
+! !
+
+!FileApplicationNoteBook::TextEditor methodsFor:'accessing'!
+
+item:aDirContentsItem
+
+
+    self stopChangeItemProcess.
+    super item:aDirContentsItem.
+    (self askForChange) isNil ifTrue:[ ^ false].
+    self setContents.
+    self startChangeItemProcess.
+    ^ true
+!
+
+presentation
+    "return the value of the instance variable 'presentation' (automatically generated)"
+
+    presentation isNil ifTrue:[
+        presentation := #asText.
+    ].
+    ^ presentation
+!
+
+presentation:something
+    "set the value of the instance variable 'presentation' (automatically generated)"
+
+    presentation := something.
+!
+
+semaChangeItem
+
+    semaChangeItem isNil ifTrue:[
+        semaChangeItem := Semaphore forMutualExclusion.
+    ].
+    ^ semaChangeItem
+! !
+
+!FileApplicationNoteBook::TextEditor methodsFor:'actions'!
+
+accept
+
+    | dir |
+
+    self masterApplication class openAnotherApplicationOnSameItem ifTrue:[
+        self updateSameFiles ifFalse:[ ^ self ].
+    ].
+    self notifyChannel value:self fileName asString, ' saved'.
+    dir := self fileName directory.
+    dir exists not ifTrue:[
+        dir recursiveMakeDirectory.
+    ].
+    editView saveAs:(self fileName).
+    self notifyChannel value:self fileName asString, ' saved'.
+    self semaChangeItem critical:[
+        self item resetItemForTextEditorChange.
+        textEditorChangeModificationTime := nil.
+        self itemChanged value:false.
+    ].
+    self modifiedChannel value:false.
+    self itemRemoved value:false.
+!
+
+askForChange
+    "ask for save changes
+    "
+
+    |answer string|
+
+    answer := false.
+    self modifiedChannel value ifTrue:[
+        self itemChanged value ifTrue:[
+            string := self fileName asString , ' was changed by someone else' 
+                        , Character cr , 'want to save your changes anyway ?'
+        ].
+        self itemRemoved value ifTrue:[
+            string := self fileName asString , ' was removed by someone else' 
+                        , Character cr , 'want to save your changes anyway ?'
+        ].
+        string := 'save changed file ' , self fileName asString , ' ?'
+    ].
+    string notNil ifTrue:[
+        answer := (Dialog confirmWithCancel:string).
+        answer isNil ifTrue:[^ answer].
+        answer == true ifTrue:[
+            self accept
+        ] ifFalse:[
+            self setContents.
+        ]
+    ].
+    ^ answer
+!
+
+changeInformation 
+
+    | stream |
+
+    stream := WriteStream with:(self getTabString).
+    masterApplication isNil ifTrue:[
+        self window label:stream contents.
+
+    ] ifFalse:[
+        masterApplication tabStringChangeTo:stream contents for:self.
+    ].
+    stream close.
+!
+
+doClose
+
+    (self askForChange) isNil ifTrue:[ ^ false].
+    self masterApplication notNil ifTrue:[
+        super doClose
+    ].
+    ^ true
+!
+
+doPrint
+    "print the contents
+    "
+    (Dialog confirm:'printing ?') ifTrue:[
+        editView doPrint.
+    ].
+!
+
+reload
+
+    self setContents.
+!
+
+setContents
+
+
+    |file contents present|
+
+    file := self fileName.
+    RecursionInterruptSignal handle:[ : ex |
+        Dialog warn:file asString, ' is too big to be loaded !!'.
+        ^ false.
+    ] do:[
+        present := self presentation.
+        present == #asText ifTrue:[
+            contents := file contents.
+        ] ifFalse:[
+            present == #hexDump ifTrue:[
+                contents := self getFileHexContents:file.
+            ]
+        ]
+    ].
+    self fileContentsModel value:contents.
+    self enableReload value:false.
+    self itemChanged value:false.
+    self modifiedChannel setValue:false.
+    self modifiedChannel changed.
+    ^ true
+!
+
+updateSameFiles
+
+    | master modifiedApplications stream filename action|
+
+    master := self masterApplication.
+    master notNil ifTrue:[
+        modifiedApplications := master getSameFilesModifiedFor:self.
+        (modifiedApplications isNil or:[modifiedApplications isEmpty]) ifTrue:[^ true ].
+        filename := self fileName asString.
+        stream := WriteStream on:''.
+        stream nextPutAll:filename.
+        stream nextPutAll:' is modified in tab'.
+        modifiedApplications size > 1 ifTrue:[
+            stream nextPutAll:'s'.
+        ].
+        stream cr.
+        modifiedApplications do:[ : el |
+            stream space.
+            stream nextPutAll:filename.
+            stream space.
+            el sameFileIndex notNil ifTrue:[
+                stream nextPutAll:el sameFileIndex asString.        
+            ].
+            stream cr.
+        ].
+        stream nextPutAll:'forget changes on other tab'.        
+        modifiedApplications size > 1 ifTrue:[
+            stream nextPutAll:'s'.
+        ].
+        stream nextPutAll:' ?'.        
+        action := Dialog 
+            choose:stream contents 
+            labels:#('cancel' 'no' 'yes') 
+            values:#(#cancel #no #yes) 
+            default:#cancel. 
+
+        stream close.
+        action == #cancel ifTrue:[ ^ false ].
+        action == #yes ifTrue:[
+            "/ here force reload for other applications
+            modifiedApplications do:[ : el |
+                el reload.
+            ]            
+        ].
+    ].
+    ^ true.
+! !
+
+!FileApplicationNoteBook::TextEditor methodsFor:'aspects'!
+
+doSaveFile
+
+    doSaveFile isNil ifTrue:[
+        doSaveFile := ValueHolder new.
+    ].
+    ^ doSaveFile.
+!
+
+enableHexToggle
+
+    enableHexToggle isNil ifTrue:[
+        enableHexToggle := true asValue.
+    ].
+    ^ enableHexToggle
+!
+
+enableReload
+
+    enableReload isNil ifTrue:[
+        enableReload := false asValue.
+"/ if your app needs to be notified of changes, uncomment one of the lines below:
+"/       enableReload addDependent:self.
+"/       enableReload onChangeSend:#enableReloadChanged to:self.
+    ].
+    ^ enableReload.
+!
+
+enableSave
+
+    enableSave isNil ifTrue:[
+        enableSave := false asValue.
+"/ if your app needs to be notified of changes, uncomment one of the lines below:
+"/       enableSave addDependent:self.
+"/       enableSave onChangeSend:#enableSaveChanged to:self.
+    ].
+    ^ enableSave.
+!
+
+fileContentsModel
+
+    fileContentsModel isNil ifTrue:[
+        fileContentsModel := ValueHolder new.
+"/ if your app needs to be notified of changes, uncomment one of the lines below:
+"/       fileContentsModel addDependent:self.
+"/       fileContentsModel onChangeSend:#fileContentsModelChanged to:self.
+    ].
+    ^ fileContentsModel.
+!
+
+itemChanged
+
+    itemChanged isNil ifTrue:[
+        itemChanged := false asValue.
+        itemChanged addDependent:self.
+    ].
+    ^ itemChanged
+!
+
+itemRemoved
+
+    itemRemoved isNil ifTrue:[
+        itemRemoved := false asValue.
+        itemRemoved addDependent:self.
+    ].
+    ^ itemRemoved
+!
+
+modifiedChannel
+
+    modifiedChannel isNil ifTrue:[
+        modifiedChannel := false asValue.
+"/ if your app needs to be notified of changes, uncomment one of the lines below:
+        modifiedChannel addDependent:self.
+"/       modifiedChannel onChangeSend:#modifiedChannelChanged to:self.
+    ].
+    ^ modifiedChannel.
+!
+
+printAsHexDump
+
+    printAsHexDump isNil ifTrue:[
+        printAsHexDump := false asValue.
+        printAsHexDump addDependent:self.
+    ].
+    ^ printAsHexDump.
+! !
+
+!FileApplicationNoteBook::TextEditor methodsFor:'change & update'!
+
+changeEnableReload
+
+    | modified changed removed |
+
+    modified := self modifiedChannel value.
+    changed := self itemChanged value.    
+    removed := self itemRemoved value.    
+
+    self enableReload value:((modified or:[changed]) and:[removed not]).
+!
+
+update:something with:aParameter from:changedObject
+    "Invoked when an object that I depend upon sends a change notification."
+
+    "stub code automatically generated - please change as required"
+
+    |modified itemRem|
+
+    changedObject == self modifiedChannel ifTrue:[
+        modified := changedObject value.
+        self enableSave value:modified.
+        self changeEnableReload.
+        ^ self
+    ].
+    changedObject == self itemRemoved ifTrue:[
+        itemRem := changedObject value.
+        itemRem == true ifTrue:[
+            self enableSave value:true.
+        ].
+        self enableHexToggle value:itemRem not.
+        self changeEnableReload.
+        ^ self
+    ].
+    changedObject == self itemChanged ifTrue:[
+        self changeEnableReload.
+        changedObject value == true ifTrue:[
+            self enableSave value:true.
+        ].
+        ^ self
+    ].
+    changedObject == self printAsHexDump ifTrue:[
+        (self askForChange) isNil ifTrue:[ 
+            self printAsHexDump value:changedObject value not withoutNotifying:self.
+            ^ self
+        ].
+        changedObject value ifTrue:[
+            self presentation:#hexDump.
+        ] ifFalse:[
+            self presentation:#asText.
+        ].
+        self changeInformation.
+        self setContents.
+        (self presentation == #hexDump) ifTrue:[
+            editView readOnly:true.   
+        ] ifFalse:[
+            editView readOnly:false.   
+        ].
+         ^ self
+    ].
+
+    super update:something with:aParameter from:changedObject
+! !
+
+!FileApplicationNoteBook::TextEditor methodsFor:'printing'!
+
+printString
+
+    ^ ('TextEditor for:', self fileName baseName)
+! !
+
+!FileApplicationNoteBook::TextEditor methodsFor:'privat-process'!
+
+checkMyItemForChanges
+
+    | dir exist myItem|
+
+    dir := self fileName directory.
+    myItem := self item.
+    exist := myItem exists.
+    self itemRemoved value:(exist not).
+    exist ifTrue:[
+        self semaChangeItem critical:[
+            | time info|
+            info := self fileName asAbsoluteFilename info.
+            time := info modified.
+            textEditorChangeModificationTime isNil ifTrue:[
+                textEditorChangeModificationTime := time.
+            ].
+            ((textEditorChangeModificationTime = time) not) ifTrue:[
+                "/ contents changed by someone else
+                textEditorChangeModificationTime := time.
+                self notifyChannel value:item fileName asString, ' was changed by someone else'.
+                self itemChanged value:true.
+            ].
+        ]
+    ]
+!
+
+getFileHexContents:f
+
+    |fileName stream data offs 
+     addrDigits col line lineStream asciiLineStream lines|
+    
+    fileName := f baseName.
+    f isDirectory ifTrue:[
+        ^ Dialog warn:(resources string:'%1 is a directory.' with:fileName).
+    ].
+    f exists ifFalse:[
+        Dialog warn:(resources string:'oops, ''%1'' is gone or unreadable.' with:fileName).
+        ^ self
+    ].
+    f isReadable ifFalse:[
+        Dialog warn:(resources string:'''%1'' is unreadable.' with:fileName).
+        ^ self
+    ].
+    f fileSize > (512*1024) ifTrue:[
+        (Dialog confirm:'Warning: the file is big (', (f fileSize//1024) printString , 'Kb). Show anyway ?')
+        ifFalse:[
+            ^ self
+        ]
+    ].
+    stream := f readStream binary.
+    data := stream contents.
+    stream close.
+
+"/        subView list:nil.
+    col := 1.
+    offs := 0.
+    lines := StringCollection new.
+
+    addrDigits := ((f fileSize + 1) log:16) truncated + 1.
+
+    lineStream := '' writeStream.
+    asciiLineStream := '' writeStream.
+
+    lineStream nextPutAll:(offs hexPrintString:addrDigits).
+    lineStream nextPutAll:': '.
+
+    data do:[:byte |
+        lineStream nextPutAll:(byte hexPrintString:2).
+        (byte between:32 and:127) ifTrue:[
+            asciiLineStream nextPut:(Character value:byte)
+        ] ifFalse:[
+            asciiLineStream nextPut:$.
+        ].
+
+        offs := offs + 1.
+        col := col + 1.
+        col > 16 ifTrue:[
+            lineStream nextPutAll:'        '.
+            lineStream nextPutAll:asciiLineStream contents.
+            lines add:(lineStream contents).
+            (offs bitAnd:16rFF) == 0 ifTrue:[
+                lines add:nil
+            ].
+            lineStream reset.
+            asciiLineStream reset.
+
+            lineStream nextPutAll:(offs hexPrintString:addrDigits).
+            lineStream nextPutAll:': '.
+            col := 1.
+        ] ifFalse:[
+            lineStream space
+        ]
+    ].
+    line := lineStream contents paddedTo:(3*16 + addrDigits + 1).
+    lines add:(line , '        ' , asciiLineStream contents).
+    ^ lines
+!
+
+startChangeItemProcess
+
+    changeItemProcess isNil ifTrue:[
+        self itemRemoved value:false.
+        self itemChanged value:false.
+        changeItemProcess := Process for:[ [   [true] whileTrue:[
+
+                                            self checkMyItemForChanges.
+                                            Delay waitForSeconds:1.0
+                                    ]
+                                ] valueNowOrOnUnwindDo:[
+                                    changeItemProcess := nil.
+                                    textEditorChangeModificationTime := nil.
+                                ]
+                              ]
+                     priority:(Processor systemBackgroundPriority).
+
+        changeItemProcess name:('TextEditorLookForModify[', self fileName baseName, ']').
+        changeItemProcess resume.
+    ].
+!
+
+stopChangeItemProcess
+
+    | task |
+
+    task := changeItemProcess.
+    task notNil ifTrue:[
+        changeItemProcess := nil.
+
+        Object errorSignal handle:[:ex|
+            Dialog warn:ex description.
+        ]do:[
+            task isDead ifFalse:[
+                task terminate.
+                task waitUntilTerminated.
+            ]
+        ]
+    ].
+! !
+
+!FileApplicationNoteBook::TextEditor methodsFor:'queries'!
+
+isModified
+
+    ^ self modifiedChannel value
+! !
+
+!FileApplicationNoteBook::TextEditor methodsFor:'startup & release'!
+
+closeRequest
+
+    (self doClose) ifTrue:[
+        ^ super closeRequest.
+    ].
+!
+
+postBuildTextEditor:aWidget
+
+    editView       := aWidget scrolledView.
+!
+
+postBuildWith:aBuilder
+
+    super postBuildWith:aBuilder.
+!
+
+postOpenWith:aBuilder
+
+    self masterApplication isNil ifTrue:[
+        self masterApplication:nil.
+        self item:(DirectoryContentsBrowser itemClass with:(Filename homeDirectory construct:'/lala/.bashrc')).
+    ].
+    self setUpTextView.
+    self changeInformation.
+    ^ super postOpenWith:aBuilder
+!
+
+release
+    "release my resources
+    "                    
+    self stopChangeItemProcess.
+    super release.
+!
+
+setUpTextView
+
+    |paranthesis col|
+
+    self item hasMimeType ifFalse:[^nil].
+    (self item mimeType isHtml) ifTrue:[
+        paranthesis := editView parenthesisSpecification.
+        ((paranthesis at:#open) includes:$<) ifFalse:[
+            col := (paranthesis at:#open) asOrderedCollection add:$<.
+            paranthesis at:#open put:col.
+        ].
+        ((paranthesis at:#close) includes:$>) ifFalse:[
+            col := (paranthesis at:#close) asOrderedCollection add:$>.
+            paranthesis at:#close put:col.
+        ]
+    ].
+! !
+
+!FileApplicationNoteBook::XViewApplication class methodsFor:'defaults'!
+
+maxNumberOfVNCRestarts
+
+    ^ 10
+!
+
+mimeTypeUnixApplicationMapping
+
+" here insert the application and mime type pairs to open by XviewApplication
+"
+
+    ^
+    #(
+        #(#'application/postscript'     #gv            )
+        #(#'application/pdf'            #acroread      )
+    )
+!
+
+tabStringFor:aApplicationType
+
+    ^ 'VNC for:'
+!
+
+wantNewApplicationAnyway
+
+    ^ false
+! !
+
+!FileApplicationNoteBook::XViewApplication class methodsFor:'interface specs'!
+
+windowSpec
+    "This resource specification was automatically generated
+     by the UIPainter of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the UIPainter may not be able to read the specification."
+
+    "
+     UIPainter new openOnClass:NoteBookApplication::XViewApplication andSelector:#windowSpec
+     NoteBookApplication::XViewApplication new openInterface:#windowSpec
+     NoteBookApplication::XViewApplication open
+    "
+
+    <resource: #canvas>
+
+    ^ 
+     #(#FullSpec
+        #name: #windowSpec
+        #window: 
+       #(#WindowSpec
+          #label: 'XView'
+          #name: 'XView'
+          #min: #(#Point 10 10)
+          #max: #(#Point 1024 768)
+          #bounds: #(#Rectangle 12 22 688 514)
+          #menu: #mainMenu
+        )
+        #component: 
+       #(#SpecCollection
+          #collection: #(
+           #(#MenuPanelSpec
+              #name: 'MenuTerminal'
+              #layout: #(#LayoutFrame 0 0.0 0 0 0 1.0 32 0)
+              #visibilityChannel: #isEmbeddedApplication
+              #menu: #menu
+              #textDefault: true
+            )
+           #(#ArbitraryComponentSpec
+              #name: 'TerminalView'
+              #layout: #(#LayoutFrame 0 0.0 32 0.0 0 1.0 0 1.0)
+              #hasHorizontalScrollBar: true
+              #hasVerticalScrollBar: true
+              #miniScrollerHorizontal: false
+              #miniScrollerVertical: false
+              #hasBorder: false
+              #component: #VNCFrameBufferView
+              #postBuildCallback: #postBuildXView:
+            )
+           )
+         
+        )
+      )
+! !
+
+!FileApplicationNoteBook::XViewApplication class methodsFor:'menu specs'!
+
+menu
+    "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:NoteBookApplication::ImageViewApplication andSelector:#menu
+     (Menu new fromLiteralArrayEncoding:(NoteBookApplication::ImageViewApplication menu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #label: 'Close'
+            #translateLabel: true
+            #isButton: true
+            #hideMenuOnActivated: false
+            #startGroup: #right
+            #value: #doClose
+            #labelImage: #(#ResourceRetriever #AbstractFileBrowser #closeIcon)
+          )
+         )
+        nil
+        nil
+      )
+! !
+
+!FileApplicationNoteBook::XViewApplication class methodsFor:'queries'!
+
+canOpenItem:aItem
+
+    | keySym canOpen|
+    
+    keySym := aItem mimeType asSymbol.
+    (OperatingSystem isUNIXlike) not ifTrue:[^ false].
+    canOpen := self mimeTypeUnixApplicationMapping detect:[ : el | (el at:1) == keySym ] ifNone:[nil].
+    canOpen isNil ifTrue:[^ false].
+     (OperatingSystem executeCommand:('which ', self UnixVNCCommand)) ifTrue:[
+        ^ true
+    ] ifFalse:[
+        (Dialog warn:'cant start viewer for '
+                        , aItem fileName baseName
+        )
+    ].
+    ^ false.
+! !
+
+!FileApplicationNoteBook::XViewApplication methodsFor:'accessing'!
+
+xView
+    "return the value of the instance variable 'imageView' (automatically generated)"
+
+    ^ xView
+!
+
+xView:something
+    "set the value of the instance variable 'imageView' (automatically generated)"
+
+    xView := something.
+! !
+
+!FileApplicationNoteBook::XViewApplication methodsFor:'actions'!
+
+changeInformation 
+
+    | stream|
+
+    stream := WriteStream on:''.
+    stream nextPutAll:'XView on: '.
+    stream nextPutAll:self fileName baseName.
+    masterApplication isNil ifTrue:[
+        self window label:stream contents.
+
+    ] ifFalse:[
+        masterApplication tabStringChangeTo:stream contents for:self.
+    ].
+    stream close.
+!
+
+setupXView
+
+    |xExt yExt fileBrowserWindow|
+
+    self startVNCserver.
+    xExt := self xView width asString.
+    fileBrowserWindow := self application:#FileBrowserV2 do:#window.
+    fileBrowserWindow isNil ifTrue:[
+        yExt := self xView height asString.
+    ] ifFalse:[
+        yExt := fileBrowserWindow height asString.
+    ].
+    ext := xExt, 'x', yExt.    
+    self startViewer.
+! !
+
+!FileApplicationNoteBook::XViewApplication methodsFor:'actions VNC'!
+
+setupView
+    |  renderer view|
+
+    view := xView.
+    renderer := VNCRenderer for:vncConnection targetWindow:view device:xView device.
+
+    view renderer:renderer.
+    view connection:vncConnection.
+
+    VNCException handle:[:ex|
+        self stopViewer.
+    ] do:[
+        vncConnection 
+            startMessageHandlerProcessForRenderer:renderer
+            errorHandler:[:ex | self stopViewer].
+    ].
+!
+
+startVNCserver
+    |cmd blocked connected numberOfVncStarts|
+
+    connected := false.
+    numberOfVncStarts isNil ifTrue:[
+        numberOfVncStarts := 1.
+    ] ifFalse:[
+        numberOfVncStarts := numberOfVncStarts + 1.
+    ].
+
+    vncLock isNil ifTrue:[vncLock := Semaphore forMutualExclusion].
+
+    vncServerPID isNil ifTrue:[
+        cmd := ('/usr/X11R6/bin/', self class UnixVNCCommand).
+        cmd asFilename exists ifFalse:[
+            cmd := self class UnixVNCCommand.
+        ].
+        vncPortNr isNil ifTrue:[
+            vncPortNr := 29
+        ].
+        cmd := cmd , ' :' , vncPortNr printString , ' nologo -nevershared -localhost -depth 16 -geometry 1024x1024'.
+
+        blocked := OperatingSystem blockInterrupts.
+
+        vncServerPID := Processor
+                   monitor:[
+                      vncServerIsTerminated := false.
+                      OperatingSystem
+                          exec:'/bin/sh'
+                          withArguments:(Array with:'sh' with:'-c' with:cmd)
+                          fileDescriptors:#()
+                          closeDescriptors:#()
+                          fork:true
+                          newPgrp:true
+                          inDirectory:nil.
+                   ]
+                   action:[:status |
+                      status stillAlive ifFalse:[
+                          OperatingSystem closePid:vncServerPID.
+                          vncLock critical:[  
+                             vncServerPID := nil.
+                             self vncServerTerminated.
+                          ].
+                      ].
+                  ].
+
+        blocked ifFalse:[
+            OperatingSystem unblockInterrupts
+        ].
+    ].
+
+    self waitForTerminationOfServer ifTrue:[
+"/        Transcript showCR:'server has terminated really - try with next port'.
+        (numberOfVncStarts < self class maxNumberOfVNCRestarts) ifTrue:[
+            vncPortNr := vncPortNr + 1.
+"/            Transcript showCR:'try next port ', vncPortNr asString.
+            self startVNCserver.
+        ] ifFalse:[
+            Dialog warn:'have started servers from port '
+                      , (vncPortNr - self class maxNumberOfVNCRestarts) asString
+                      , ' to '
+                      , vncPortNr
+                      , ' - cant connect anyway'.
+"/            Transcript showCR:'have started servers from port ', vncPortNr - self class maxNumberOfVNCRestarts, ' to ', vncPortNr.
+        ].
+    ] ifFalse:[
+        vncLock critical:[  
+            vncServerPID isNil ifTrue:[
+                Dialog warn:'Cannot start Xvnc'.
+            ] ifFalse:[
+                VNCAuthenticationFailure handle:[:ex |
+                    Dialog warn:'Wrong password'.
+                ] do:[
+                    connected := self vncConnect.
+                ].
+                connected ifTrue:[self setupView].
+            ].
+        ].
+    ].
+!
+
+stopVNCServer
+
+    vncServerPID notNil ifTrue:[
+        OperatingSystem terminateProcess:vncServerPID.
+        Delay waitForSeconds:0.2.
+        vncServerPID notNil ifTrue:[
+            OperatingSystem killProcess:vncServerPID.
+            vncServerPID := nil.
+        ].
+    ].
+    self vncServerTerminated.
+!
+
+vncConnect
+    |  tryConnects|
+
+    vncConnection notNil ifTrue:[
+        vncConnection close
+    ].
+
+    vncConnection := VNCServerConnection new.
+    tryConnects := 1.
+    [tryConnects < 3] whileTrue:[
+        VNCConnectionFailure handle:[:ex |
+            Delay waitForSeconds:0.5.
+            tryConnects := tryConnects + 1.
+        ] do:[
+            vncConnection connectTo:'localhost' port:vncPortNr.
+            ^ true.
+        ].
+    ].
+    ^ false
+!
+
+vncServerTerminated
+"/    Transcript showCR:'vnc server has terminated'.
+"/    'vnc server has terminated' errorPrintCR.
+    "/ Dialog information:'vnc server has terminated'.
+
+    self stopViewer.
+    vncConnection notNil ifTrue:[
+        vncConnection close.
+        vncConnection := nil
+    ].
+    vncServerIsTerminated := true.
+!
+
+waitForTerminationOfServer
+    | cycles |
+
+    cycles := 1.
+    [vncServerIsTerminated] whileFalse:[
+        (cycles > 3) ifTrue:[^ false].
+        cycles := cycles + 1.
+        Delay waitForSeconds:0.5.
+    ].
+    ^ true
+! !
+
+!FileApplicationNoteBook::XViewApplication methodsFor:'actions viewer'!
+
+startViewer
+    |cmd keySym applItem |
+
+    keySym := self item mimeType asSymbol.
+    applItem := self class mimeTypeUnixApplicationMapping detect:[ : el | (el at:1) == keySym ] ifNone:[nil].
+    applItem isNil ifTrue:[ ^ self].
+    
+    cmd := (applItem at:2) asString, ' -geometry ', ext, ' -display :' , vncPortNr printString , ' ' , self fileName asString.
+    self startViewer:cmd
+!
+
+startViewer:viewerCommand
+    |blocked|
+
+    viewerPID notNil ifTrue:[
+        ^ self
+    ].
+
+    blocked := OperatingSystem blockInterrupts.
+
+    viewerPID := Processor
+               monitor:[
+                  OperatingSystem
+                      exec:'/bin/sh'
+                      withArguments:(Array with:'sh' with:'-c' with:viewerCommand)
+                      fileDescriptors:#()
+                      closeDescriptors:#()
+                      fork:true
+                      newPgrp:true
+                      inDirectory:nil.
+               ]
+               action:[:status |
+                  status stillAlive ifFalse:[
+                      OperatingSystem closePid:viewerPID.
+                      viewerPID := nil.
+                      self viewerTerminated.
+                  ].
+               ].
+
+    blocked ifFalse:[
+        OperatingSystem unblockInterrupts
+    ].
+
+    viewerPID isNil ifTrue:[
+        Dialog warn:'Cannot start ', viewerCommand.
+    ].
+!
+
+startXterm
+    |cmd|
+
+    cmd := 'xterm -geometry 600x800 -display :' , vncPortNr printString.
+    self startViewer:cmd
+!
+
+stopViewer
+    viewerPID notNil ifTrue:[
+        OperatingSystem terminateProcess:viewerPID.
+        Delay waitForSeconds:0.2.
+        viewerPID notNil ifTrue:[
+            OperatingSystem killProcess:viewerPID.
+            viewerPID := nil.
+        ]
+    ].
+!
+
+viewerTerminated
+"/    Transcript showCR:'viewer has terminated'.
+"/    'viewer has terminated' errorPrintCR.
+    "/ Dialog information:'viewer has terminated'.
+! !
+
+!FileApplicationNoteBook::XViewApplication methodsFor:'initialization & release'!
+
+postBuildXView:aWidget
+
+    self xView:aWidget scrolledView.
+    self xView wantsFocusWithPointerEnter.
+    aWidget autoHideScrollBars:true.
+!
+
+postOpenWith:aBuilder 
+    "
+    only invoked if the application not started from a master
+    "
+
+    |currentDir contents suffix fileName|
+
+    self masterApplication isNil ifTrue:[
+        self masterApplication:nil.
+        currentDir := Filename homeDirectory.
+        contents := currentDir directoryContents.
+        fileName := contents 
+                    detect:[:file | 
+                        suffix := file asFilename suffix asLowercase.
+                        suffix = 'pdf'
+                    ]
+                    ifNone:[nil].
+        fileName isNil ifTrue:[
+            Dialog warn:'cant find a PDF File in ' , currentDir asString.
+            ^ self
+        ].
+        self item:(DirectoryContentsBrowser itemClass with:(currentDir construct:fileName)).
+    ].
+    self changeInformation.
+    self setupXView.
+    ^ super postOpenWith:aBuilder
+!
+
+release
+"/Transcript showCR:'release'.
+    self stopViewer.
+    self stopVNCServer.
+    ^ super release
+! !
+
+!FileApplicationNoteBook class methodsFor:'documentation'!
+
+version
+    ^ '$Header: /cvs/stx/stx/libtool/FileApplicationNoteBook.st,v 1.1 2002-09-25 07:59:29 penk Exp $'
+! !
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FileBrowserV2.st	Wed Sep 25 10:00:32 2002 +0200
@@ -0,0 +1,1372 @@
+"
+ COPYRIGHT (c) 1991 by Claus Gittinger
+              All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice.   This software may not
+ be provided or otherwise made available to, or used by, any
+ other person.  No title to or ownership of the software is
+ hereby transferred.
+"
+
+"{ Package: 'stx:libtool' }"
+
+AbstractFileBrowser subclass:#FileBrowserV2
+	instanceVariableNames:'fileEntryFieldHolder'
+	classVariableNames:'Icons'
+	poolDictionaries:''
+	category:'Interface-Tools-File'
+!
+
+!FileBrowserV2 class methodsFor:'documentation'!
+
+copyright
+"
+ COPYRIGHT (c) 1991 by Claus Gittinger
+              All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice.   This software may not
+ be provided or otherwise made available to, or used by, any
+ other person.  No title to or ownership of the software is
+ hereby transferred.
+"
+!
+
+documentation
+"
+    FileBrowserV2 is based on Filebrowser created by Claus Gittinger
+
+    WARNING: files edited with FileBrowser will have leading spaces (multiple-8)
+             being replaced by tabs. If tabs are to be preserved at other
+             positions (for example, sendmail-config files) they will be
+             corrupt after being written.
+
+    [instance variables]:
+
+        checkDelta      <Integer>       number of seconds of check interval
+                                        (looks ever so often if shown directory
+                                         has changed). You may make this number
+                                        higher, if your network-times are
+                                        incorrect and thus, the filebrowser
+                                        checks too often.
+
+        compressTabs    <Boolean>       if true, leading spaces will be
+                                        replaced by tabs when saving text
+
+    some of the defaults (long/short list etc.) can be set by the resource file;
+    see FileBrowser>>initialize for more details..
+
+    [author:]
+        Christian Penk
+
+    [start with:]
+        FileBrowserV2 open
+"
+! !
+
+!FileBrowserV2 class methodsFor:'instance creation'!
+
+on:aDirectoryPath
+    "return a new FileBrowserV2 in a pathname"
+
+    | instance|
+    instance := self new.
+    instance currentFileNameHolder value:(Array with:aDirectoryPath).
+    ^ instance
+
+"/    | instance builder|
+"/
+"/    builder := super open.
+"/    instance := builder application.
+"/    instance currentFileNameHolder value:aDirectoryPath.
+"/    ^ instance
+
+    "
+     (FileBrowserV2 on:'/usr/local/bin') open
+     (FileBrowserV2 on:'/etc'          ) open
+     (FileBrowserV2 on:'..'            ) open
+     (FileBrowserV2 on:'.'             ) open
+    "
+!
+
+open
+    "start a new FileBrowserV2"
+
+    | instance |
+    instance := self new.
+    instance open.
+    ^ instance
+    "
+     FileBrowserV2 openOn:'/etc'           withExtent:800@600
+     FileBrowserV2 openOn:'..'             withExtent:200@300
+     FileBrowserV2 openOn:'.'              withExtent:1024@768
+    "
+!
+
+openOn:aDirectoryPath 
+    "start a new FileBrowserV2 in a pathname"
+
+    | instance|
+    instance := self on:aDirectoryPath asFilename.
+    ^ instance open.
+    "
+     FileBrowserV2 openOn:'/etc'           
+     FileBrowserV2 openOn:'..'           
+     FileBrowserV2 openOn:'.'             
+    "
+!
+
+openOn:aDirectoryPath withExtent:extent
+    "start a new FileBrowserV2 in a pathname"
+
+    | instance builder|
+    instance := self on:aDirectoryPath.
+    builder := instance open.
+    builder window extent:extent.
+    ^ instance
+    "
+     FileBrowserV2 openOn:'/etc'           withExtent:800@600
+     FileBrowserV2 openOn:'..'             withExtent:200@300
+     FileBrowserV2 openOn:'.'              withExtent:1024@768
+    "
+!
+
+openWithAspects:someAspects withExtent:extent
+    "start a new FileBrowserV2 in a pathname"
+
+    |dir clone|
+
+    dir := someAspects at:#currentFileNameHolder ifAbsent:nil.
+    clone := self openOn:(dir value) withExtent:extent.
+
+    "
+     FileBrowserV2 openOn:'/etc'           withExtent:800@600
+     FileBrowserV2 openOn:'..'             withExtent:200@300
+     FileBrowserV2 openOn:'.'              withExtent:1024@768
+    "
+! !
+
+!FileBrowserV2 class methodsFor:'class initialization'!
+
+clearHistoryIcon
+    ^ Icon deleteIcon
+!
+
+initialize
+
+    self installInLauncher.
+!
+
+initializeDefaultCommands
+    DefaultCommandPerMIME := Dictionary new.
+
+    DefaultCommandPerMIME at:'application/x-tar-compressed' put:'gunzip < %1 | tar tvf -'.
+    DefaultCommandPerMIME at:'application/pdf'              put:'acroread %1'.
+
+    "
+     self initializeDefaultCommands
+    "
+!
+
+installInLauncher
+    "add myself to the launcher menu and toolBar"
+
+    |menuItem icon action|
+
+    FileBrowserV2 isNil ifTrue:[^ self].
+
+    action := [FileBrowserV2 open].
+
+    icon := self defaultIcon magnifiedTo:28@28.
+
+    menuItem := MenuItem new 
+                    label: 'FileBrowser V2';
+                    value: action;
+                    isButton: false;
+                    labelImage: (LabelAndIcon icon:icon string:'FileBrowser V2');
+                    nameKey: #fileBrowserV2;
+                    activeHelpKey: #fileBrowserV2;
+                    submenuChannel: #menuFileHistory;
+                    showBusyCursorWhilePerforming:true.
+
+    NewLauncher addMenuItem:menuItem in:'menu.file' position:#( #before #fileBrowser) space:true.
+
+    menuItem := MenuItem new 
+                    label: 'FileBrowser V2';
+                    value: action;
+                    isButton: true;
+                    labelImage: icon;
+                    nameKey: #fileBrowserV2;
+                    activeHelpKey: #fileBrowserV2;
+                    submenuChannel: #menuFileHistory;
+                    showBusyCursorWhilePerforming:true.
+
+    NewLauncher addMenuItem:menuItem in:'toolbar' position:#( #before #fileBrowser) space:false.
+
+    "
+     self installInLauncher
+     self removeFromLauncher
+    "
+!
+
+removeFromLauncher
+    "/
+    "/ remove myself from the launcher menu
+    "/
+
+    NewLauncher isNil ifTrue:[^ self].
+    NewLauncher removeUserTool:#fileBrowserV2
+
+    "
+     self removeFromLauncher
+    "
+! !
+
+!FileBrowserV2 class methodsFor:'defaults'!
+
+entryFieldEndStringForMultipleSelection
+
+    ^ ('[*]')
+! !
+
+!FileBrowserV2 class methodsFor:'help specs'!
+
+flyByHelpSpec
+    <resource: #help>
+
+    |spec|
+
+    spec := super flyByHelpSpec addPairsFrom:#(
+
+#addTerminal
+'Shell Terminal'
+
+#searchFile
+'Search a File'
+
+#directoryUp
+'Up'
+
+#directoryBack
+'Back'
+
+#copyFile
+'CopyFile'
+
+#cutFile
+'CutFile'
+
+#fileHome
+'Home'
+
+#pasteFile
+'PasteFile'
+
+#deleteFile
+'DeleteFile'
+
+#fileIn
+'FileIn'
+
+#directoryForward
+'Forward'
+
+#directoryHistory
+'Directory'
+
+#fileHistory
+'History'
+
+#hideToolBar
+'Hide Toolbar'
+
+#hideFilenameEntryField
+'Hide Filename Field'
+
+).
+
+    ^ spec.
+! !
+
+!FileBrowserV2 class methodsFor:'icon'!
+
+defaultIcon
+    "This resource specification was automatically generated
+     by the ImageEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the ImageEditor may not be able to read the specification."
+
+    "
+     self defaultIcon inspect
+     ImageEditor openOnClass:self andSelector:#defaultIcon
+    "
+
+    <resource: #image>
+
+    ^Icon
+        constantNamed:#'FileBrowserV2 class defaultIcon'
+        ifAbsentPut:[(Depth4Image new) width: 28; height: 28; photometric:(#palette); bitsPerSample:(#(4 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+@@@@@@@@@@@@@@@@@@@@CLA&Y&Y&Y&X@@ADP@@@L0F@@@@@@A @ADAD@@@3@XN;.;.8F@ADPDQ@@CLA ;.@@@@@@D@@@D@@L0FC.8O[6=/@QDADP@@3@X@; 
+[6=/[0DPDP@@CLA DNC6<@@F<ADP@@@L0F@A@F= [0= @@@@@@3@X@@P=/[6=/@@@@@@CLA @@A/[6=/X@@@@@@L0FC0@O[6=/[0@@@@@@3@XF<@@@@@@@@@
+@@@@CLA = @@@@@@@@@@@@@L0FA/[6=/A @@@@@@@@3@XO[6=/XF@@@@@@@@CLA @@@@@@X@@@@@@@@L0FY&Y&Y&Y @@@@@@@@C@Y&Y&Y&Y&@@@@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@N@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@C @b') ; colorMapFromArray:#[0 0 0 255 255 255 255 0 0 0 255 0 0 0 255 0 255 255 255 255 0 255 0 255 127 0 0 0 127 0 0 0 127 0 127 127 127 127 0 127 0 127 127 127 127 170 170 170]; mask:((Depth1Image new) width: 28; height: 28; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
+O??# C??9<@??>? O???<C????@????0O???8C???<@???>@O??<@C???@@???0@O??<@C??8@@??>@@O?? @C??8@@??>@@G?? @@??8@@@@@@@G.P=0AAD
+HP@PQBD@GDP8 AADHD@PQBA@DN^=0@@a') ; yourself); yourself]
+!
+
+hideFilenameEntryFieldIcon
+    <resource: #programImage>
+
+    ^ ToolbarIconLibrary hideToolbarIconH14
+!
+
+hideToolBarIcon
+    <resource: #programImage>
+
+    ^ ToolbarIconLibrary hideToolbarIconH26
+! !
+
+!FileBrowserV2 class methodsFor:'interface specs'!
+
+windowSpec
+    "This resource specification was automatically generated
+     by the UIPainter of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the UIPainter may not be able to read the specification."
+
+    "
+     UIPainter new openOnClass:FileBrowserV2 andSelector:#windowSpec
+     FileBrowserV2 new openInterface:#windowSpec
+     FileBrowserV2 open
+    "
+
+    <resource: #canvas>
+
+    ^ 
+     #(#FullSpec
+        #name: #windowSpec
+        #window: 
+       #(#WindowSpec
+          #label: #FileBrowser
+          #name: #FileBrowser
+          #min: #(#Point 10 10)
+          #max: #(#Point 1152 864)
+          #bounds: #(#Rectangle 16 42 816 642)
+          #menu: #mainMenu
+        )
+        #component: 
+       #(#SpecCollection
+          #collection: #(
+           #(#ViewSpec
+              #name: 'ToolbarBox'
+              #layout: #(#LayoutFrame 0 0 0 0 0 1 30 0)
+              #level: 0
+              #visibilityChannel: #toolBarVisibleHolder
+              #component: 
+             #(#SpecCollection
+                #collection: #(
+                 #(#ActionButtonSpec
+                    #label: 'hideToolBarIcon'
+                    #name: 'HideToolBarButton'
+                    #layout: #(#LayoutFrame 0 0 0 0 13 0 30 0)
+                    #activeHelpKey: #hideToolBar
+                    #hasCharacterOrientedLabel: false
+                    #translateLabel: true
+                    #model: #hideToolbar
+                    #postBuildCallback: #hideToolBarButtonCreated:
+                  )
+                 #(#MenuPanelSpec
+                    #name: 'ToolBar'
+                    #layout: #(#LayoutFrame 13 0 0 0 0 1 30 0)
+                    #menu: #toolBarMainMenu
+                    #textDefault: true
+                  )
+                 )
+               
+              )
+            )
+           #(#ViewSpec
+              #name: 'FilenameEntryFieldBox'
+              #layout: #(#LayoutFrame 0 0 30 0 0 1 55 0)
+              #level: 0
+              #visibilityChannel: #filenameEntryFieldVisibleHolder
+              #component: 
+             #(#SpecCollection
+                #collection: #(
+                 #(#ActionButtonSpec
+                    #label: 'hideFilenameEntryFieldIcon'
+                    #name: 'HideFilenameEntryFieldButton'
+                    #layout: #(#LayoutFrame 0 0 0 0 13 0 0 1)
+                    #activeHelpKey: #hideFilenameEntryField
+                    #hasCharacterOrientedLabel: false
+                    #translateLabel: true
+                    #model: #hideFilenameEntryField
+                    #postBuildCallback: #hideFilenameEntryFieldButtonCreated:
+                  )
+                 #(#ViewSpec
+                    #name: 'Box1'
+                    #layout: #(#LayoutFrame 13 0.0 0 0.0 0 1.0 0 1.0)
+                    #level: 1
+                    #component: 
+                   #(#SpecCollection
+                      #collection: #(
+                       #(#VariableHorizontalPanelSpec
+                          #name: 'VariableHorizontalPanel1'
+                          #layout: #(#LayoutFrame 1 0.0 1 0.0 -1 1.0 -1 1.0)
+                          #level: 0
+                          #showHandle: true
+                          #component: 
+                         #(#SpecCollection
+                            #collection: #(
+                             #(#FilenameInputFieldSpec
+                                #name: 'FilenameEntryField'
+                                #level: 1
+                                #model: #fileEntryFieldHolder
+                                #acceptOnPointerLeave: false
+                                #postBuildCallback: #postBuildPathField:
+                              )
+                             #(#ViewSpec
+                                #name: 'FilterBox'
+                                #component: 
+                               #(#SpecCollection
+                                  #collection: #(
+                                   #(#LabelSpec
+                                      #label: 'Filter:'
+                                      #name: 'Filter'
+                                      #layout: #(#LayoutFrame 0 0 0 0 40 0 0 1)
+                                      #translateLabel: true
+                                      #adjust: #left
+                                      #postBuildCallback: #postBuildPathViewBox:
+                                    )
+                                   #(#ComboBoxSpec
+                                      #name: 'FilterSelectionBox'
+                                      #layout: #(#LayoutFrame 40 0 0 0 0 1 0 1)
+                                      #model: #filterModel
+                                      #immediateAccept: true
+                                      #acceptOnPointerLeave: false
+                                      #comboList: #filterListModel
+                                    )
+                                   )
+                                 
+                                )
+                                #postBuildCallback: #postBuildPathViewBox:
+                              )
+                             )
+                           
+                          )
+                          #handles: #(#Any 0.8 1.0)
+                          #postBuildCallback: #postBuildPathViewBox:
+                        )
+                       )
+                     
+                    )
+                    #postBuildCallback: #postBuildPathViewBox:
+                  )
+                 )
+               
+              )
+            )
+           #(#ViewSpec
+              #name: 'BrowserBox'
+              #layout: #(#LayoutFrame 0 0.0 55 0 0 1.0 -20 1)
+              #level: 0
+              #component: 
+             #(#SpecCollection
+                #collection: #(
+                 #(#'FileBrowserV2UISpecifications::PanelSpec'
+                    #name: 'VerticalPanel'
+                    #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
+                    #level: 0
+                    #whichView: #last
+                    #orientation: #vertical
+                    #visibility: #viewNoteBookApplicationHolder
+                    #component: 
+                   #(#SpecCollection
+                      #collection: #(
+                       #(#'FileBrowserV2UISpecifications::PanelSpec'
+                          #name: 'HorizontalPanel'
+                          #level: 0
+                          #whichView: #first
+                          #orientation: #horizontal
+                          #visibility: #showDirectoryTreeHolder
+                          #component: 
+                         #(#SpecCollection
+                            #collection: #(
+                             #(#SubCanvasSpec
+                                #name: 'DirectoryTreeBrowser'
+                                #hasHorizontalScrollBar: false
+                                #hasVerticalScrollBar: false
+                                #majorKey: #DirectoryTreeBrowser
+                                #createNewApplication: true
+                                #createNewBuilder: true
+                              )
+                             #(#SubCanvasSpec
+                                #name: 'DirectoryContentsBrowser'
+                                #hasHorizontalScrollBar: false
+                                #hasVerticalScrollBar: false
+                                #majorKey: #DirectoryContentsBrowser
+                                #createNewApplication: true
+                                #createNewBuilder: true
+                              )
+                             )
+                           
+                          )
+                          #handles: #(#Any 0.229621 1.0)
+                        )
+                       #(#SubCanvasSpec
+                          #name: 'FileApplicationNoteBook'
+                          #hasHorizontalScrollBar: false
+                          #hasVerticalScrollBar: false
+                          #majorKey: #FileApplicationNoteBook
+                          #createNewApplication: true
+                          #createNewBuilder: true
+                        )
+                       )
+                     
+                    )
+                    #handles: #(#Any 0.5 1.0)
+                  )
+                 )
+               
+              )
+            )
+           #(#ViewSpec
+              #name: 'Box2'
+              #layout: #(#LayoutFrame 0 0 -20 1 0 1 0 1)
+              #level: 0
+              #component: 
+             #(#SpecCollection
+                #collection: #(
+                 #(#LabelSpec
+                    #label: 'NotifyLabel'
+                    #name: 'NotifyLabel'
+                    #layout: #(#LayoutFrame 1 0.0 1 0.0 1 1.0 1 1.0)
+                    #level: -1
+                    #translateLabel: true
+                    #labelChannel: #notifyChannel
+                    #adjust: #left
+                  )
+                 )
+               
+              )
+            )
+           )
+         
+        )
+      )
+! !
+
+!FileBrowserV2 class methodsFor:'menu specs'!
+
+browserMenu
+    "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:FileBrowserV2 andSelector:#browserMenu
+     (Menu new fromLiteralArrayEncoding:(FileBrowserV2 browserMenu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #label: 'Spawn'
+            #translateLabel: true
+            #value: #doSpawn
+          )
+         #(#MenuItem
+            #label: 'Save Settings'
+            #translateLabel: true
+            #value: #saveSettingsAspectValues
+          )
+         #(#MenuItem
+            #label: '-'
+          )
+         #(#MenuItem
+            #label: 'Search File'
+            #translateLabel: true
+            #value: #doOpenSearchFile
+          )
+         #(#MenuItem
+            #label: 'Terminal View'
+            #translateLabel: true
+            #value: #doAddTerminal
+          )
+         #(#MenuItem
+            #label: '-'
+          )
+         #(#MenuItem
+            #label: 'Exit'
+            #translateLabel: true
+            #value: #closeRequest
+          )
+         )
+        nil
+        nil
+      )
+!
+
+mainMenu
+    "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:FileBrowserV2 andSelector:#mainMenu
+     (Menu new fromLiteralArrayEncoding:(FileBrowserV2 mainMenu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #label: 'Browser'
+            #translateLabel: true
+            #submenuChannel: #browserMenu
+          )
+         #(#MenuItem
+            #label: 'Directory'
+            #translateLabel: true
+            #submenuChannel: #directoryMenu
+          )
+         #(#MenuItem
+            #label: 'File'
+            #translateLabel: true
+            #submenuChannel: #fileMenu
+          )
+         #(#MenuItem
+            #label: 'Edit'
+            #translateLabel: true
+            #submenuChannel: #editMenu
+          )
+         #(#MenuItem
+            #label: 'View'
+            #translateLabel: true
+            #submenu: 
+           #(#Menu
+              #(
+               #(#MenuItem
+                  #label: 'View File List'
+                  #translateLabel: true
+                  #submenuChannel: #viewFileBrowserMenu
+                )
+               #(#MenuItem
+                  #label: 'Sort File List'
+                  #translateLabel: true
+                  #submenuChannel: #sortMenu
+                )
+               #(#MenuItem
+                  #label: 'View Tree View'
+                  #translateLabel: true
+                  #indication: #showDirectoryTreeHolder
+                )
+               #(#MenuItem
+                  #label: 'View Directory Description'
+                  #translateLabel: true
+                  #indication: #viewDirectoryDescription
+                )
+               #(#MenuItem
+                  #label: 'View Files in Tree View'
+                  #translateLabel: true
+                  #indication: #viewFilesInDirectoryTree
+                )
+               #(#MenuItem
+                  #label: 'View Directories in Contents View'
+                  #translateLabel: true
+                  #indication: #viewDirectoriesInDirectoryContentsBrowser
+                )
+               #(#MenuItem
+                  #label: 'View Notebook Applications'
+                  #translateLabel: true
+                  #enabled: #enableViewNoteBookApplication
+                  #indication: #viewNoteBookApplicationHolder
+                )
+               #(#MenuItem
+                  #label: 'Open Multiple Applications'
+                  #translateLabel: true
+                  #indication: #openMultipleApplicationsForType
+                )
+               #(#MenuItem
+                  #label: '-'
+                )
+               #(#MenuItem
+                  #label: 'Toolbar'
+                  #translateLabel: true
+                  #hideMenuOnActivated: false
+                  #indication: #toolBarVisibleHolder
+                )
+               #(#MenuItem
+                  #label: 'Pathname '
+                  #translateLabel: true
+                  #hideMenuOnActivated: false
+                  #indication: #filenameEntryFieldVisibleHolder
+                )
+               #(#MenuItem
+                  #label: '-'
+                )
+               #(#MenuItem
+                  #label: 'Update'
+                  #translateLabel: true
+                )
+               )
+              nil
+              nil
+            )
+          )
+         #(#MenuItem
+            #label: 'Tools'
+            #translateLabel: true
+            #submenuChannel: #toolsMenuSpec
+          )
+         #(#MenuItem
+            #label: 'CVS'
+            #translateLabel: true
+            #submenu: 
+           #(#Menu
+              #(
+               #(#MenuItem
+                  #label: 'Update selected Files/Directories'
+                  #translateLabel: true
+                  #value: #cvsUpdateSelection
+                  #enabled: #hasSelection
+                )
+               #(#MenuItem
+                  #label: 'Update Directory Local'
+                  #translateLabel: true
+                  #value: #cvsUpdateAll
+                )
+               #(#MenuItem
+                  #label: 'Update Directory Recursive'
+                  #translateLabel: true
+                  #value: #cvsUpdateAllRecursive
+                )
+               #(#MenuItem
+                  #label: '-'
+                )
+               #(#MenuItem
+                  #label: 'Commit...'
+                  #translateLabel: true
+                  #value: #cvsCommit
+                )
+               #(#MenuItem
+                  #label: 'Add && Commit...'
+                  #translateLabel: true
+                  #value: #cvsAddAndCommit
+                  #enabled: #canCvsAddAndCommit
+                )
+               #(#MenuItem
+                  #label: '-'
+                )
+               #(#MenuItem
+                  #label: 'Remove File && CVS Container...'
+                  #translateLabel: true
+                  #value: #cvsRemoveFileAndCVSContainer
+                  #enabled: #canRemoveCVSContainer
+                )
+               )
+              nil
+              nil
+            )
+          )
+         #(#MenuItem
+            #label: 'Help'
+            #translateLabel: true
+            #startGroup: #right
+            #submenu: 
+           #(#Menu
+              #(
+               #(#MenuItem
+                  #label: 'FileBrowser Documentation'
+                  #translateLabel: true
+                )
+               #(#MenuItem
+                  #label: '-'
+                )
+               #(#MenuItem
+                  #label: 'About FileBrowser...'
+                  #translateLabel: true
+                )
+               )
+              nil
+              nil
+            )
+          )
+         )
+        nil
+        nil
+      )
+!
+
+toolBarMainMenu
+    "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:FileBrowserV2 andSelector:#toolBarMainMenu
+     (Menu new fromLiteralArrayEncoding:(FileBrowserV2 toolBarMainMenu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #label: 'DirectoryUp'
+            #translateLabel: true
+            #isButton: true
+            #value: #doGoDirectoryUp
+            #activeHelpKey: #directoryUp
+            #enabled: #enableDirectoryUp
+            #labelImage: #(#ResourceRetriever #AbstractFileBrowser #upArrow20x20Icon)
+          )
+         #(#MenuItem
+            #label: ''
+          )
+         #(#MenuItem
+            #label: 'Back'
+            #translateLabel: true
+            #isButton: true
+            #value: #doBack
+            #activeHelpKey: #directoryBack
+            #enabled: #enableBack
+            #labelImage: #(#ResourceRetriever #AbstractFileBrowser #leftArrow20x20PlusMenuIcon)
+            #submenuChannel: #menuDirHistoryBack
+          )
+         #(#MenuItem
+            #label: ''
+          )
+         #(#MenuItem
+            #label: 'Forward'
+            #translateLabel: true
+            #isButton: true
+            #value: #doForward
+            #activeHelpKey: #directoryForward
+            #enabled: #enableForward
+            #labelImage: #(#ResourceRetriever #AbstractFileBrowser #rightArrowPlusMenu20x20Icon)
+            #submenuChannel: #menuFileHistory
+          )
+         #(#MenuItem
+            #label: ''
+          )
+         #(#MenuItem
+            #label: 'Home'
+            #translateLabel: true
+            #isButton: true
+            #value: #doGotoHomeDirectory
+            #activeHelpKey: #fileHome
+            #enabled: #enableHome
+            #labelImage: #(#ResourceRetriever nil #goHomeIcon)
+          )
+         #(#MenuItem
+            #label: ''
+          )
+         #(#MenuItem
+            #label: 'File History'
+            #translateLabel: true
+            #isButton: true
+            #activeHelpKey: #fileHistory
+            #enabled: #enableFileHistory
+            #labelImage: #(#ResourceRetriever #ToolbarIconLibrary #history20x20Icon)
+            #submenuChannel: #menuFileHistory
+          )
+         #(#MenuItem
+            #label: ''
+          )
+         #(#MenuItem
+            #label: 'Copy'
+            #translateLabel: true
+            #isButton: true
+            #value: #copyInDirContentsBrowser
+            #activeHelpKey: #copyFile
+            #enabled: #hasSelection
+            #labelImage: #(#ResourceRetriever #ToolbarIconLibrary #copy20x20Icon)
+          )
+         #(#MenuItem
+            #label: 'Cut'
+            #translateLabel: true
+            #isButton: true
+            #value: #cutInDirContentsBrowser
+            #activeHelpKey: #cutFile
+            #enabled: #hasSelection
+            #labelImage: #(#ResourceRetriever #ToolbarIconLibrary #cut20x20Icon2)
+          )
+         #(#MenuItem
+            #label: 'Paste'
+            #translateLabel: true
+            #isButton: true
+            #value: #pasteFiles
+            #activeHelpKey: #pasteFile
+            #enabled: #canPaste
+            #labelImage: #(#ResourceRetriever #ToolbarIconLibrary #paste20x20Icon)
+          )
+         #(#MenuItem
+            #label: 'Delete'
+            #translateLabel: true
+            #isButton: true
+            #value: #deleteInDirContentsBrowser
+            #activeHelpKey: #deleteFile
+            #enabled: #hasSelection
+            #labelImage: #(#ResourceRetriever #ToolbarIconLibrary #erase20x20Icon)
+          )
+         #(#MenuItem
+            #label: ''
+          )
+         #(#MenuItem
+            #label: 'File In'
+            #translateLabel: true
+            #isButton: true
+            #value: #fileFileIn
+            #activeHelpKey: #fileIn
+            #enabled: #hasSelection
+            #labelImage: #(#ResourceRetriever #ToolbarIconLibrary #fileIn20x20Icon3)
+          )
+         #(#MenuItem
+            #label: ''
+          )
+         #(#MenuItem
+            #label: 'Search File'
+            #translateLabel: true
+            #isButton: true
+            #value: #doOpenSearchFile
+            #activeHelpKey: #searchFile
+            #labelImage: #(#ResourceRetriever #ToolbarIconLibrary #search20x20Icon)
+          )
+         #(#MenuItem
+            #label: 'VT100'
+            #translateLabel: true
+            #isButton: true
+            #value: #doAddTerminal
+            #activeHelpKey: #addTerminal
+            #labelImage: #(#ResourceRetriever #ToolbarIconLibrary #shell20x20WithoutTextIcon)
+          )
+         )
+        nil
+        nil
+      )
+!
+
+toolsMenuSpec
+    "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:FileBrowserV2 andSelector:#toolsMenuSpec
+     (Menu new fromLiteralArrayEncoding:(FileBrowserV2 toolsMenuSpec)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #label: 'Execute Command...'
+            #translateLabel: true
+            #value: #doExecuteCommand
+          )
+         #(#MenuItem
+            #label: 'Shell Terminal'
+            #translateLabel: true
+            #isVisible: #canDoTerminalAndSystemIsUnix
+            #value: #openTerminal
+            #enabled: #canDoTerminal
+          )
+         #(#MenuItem
+            #label: 'DOS Terminal'
+            #translateLabel: true
+            #isVisible: #canDoTerminalAndSystemIsDOS
+            #value: #openTerminal
+            #enabled: #canDoTerminal
+          )
+         #(#MenuItem
+            #label: '-'
+          )
+         #(#MenuItem
+            #label: 'Changes Browser'
+            #translateLabel: true
+            #value: #openChangesBrowser
+            #enabled: #hasSelection
+          )
+         #(#MenuItem
+            #label: 'Snapshot Image Browser'
+            #translateLabel: true
+            #value: #openSnapshotImageBrowser
+            #enabled: #hasSnapshotSelection
+          )
+         #(#MenuItem
+            #label: 'Create Smalltalk Project'
+            #translateLabel: true
+            #value: #createProjectAndOpenProjectBrowser
+            #enabled: #canCreateNewProject
+          )
+         #(#MenuItem
+            #label: 'Install Autoloaded'
+            #translateLabel: true
+            #value: #readAbbrevFile
+            #enabled: #canReadAbbrevFile
+          )
+         #(#MenuItem
+            #label: 'Install all as Autoloaded'
+            #translateLabel: true
+            #value: #installAllAsAutoloaded
+            #enabled: #anySTFilesPresent
+          )
+         #(#MenuItem
+            #label: 'Editor'
+            #translateLabel: true
+            #value: #openEditor
+            #enabled: #hasSelection
+          )
+         #(#MenuItem
+            #label: 'HTML Reader'
+            #translateLabel: true
+            #value: #openHTMLReader
+            #enabled: #hasSelection
+          )
+         #(#MenuItem
+            #label: 'ASN1 Browser'
+            #translateLabel: true
+            #isVisible: #hasASN1
+            #value: #openASN1Browser
+            #enabled: #hasASN1AndSelection
+          )
+         #(#MenuItem
+            #label: 'C Browser'
+            #translateLabel: true
+            #isVisible: #hasCBrowser
+            #value: #openCBrowser
+            #enabled: #hasCBrowser
+          )
+         #(#MenuItem
+            #label: 'Applet Viewer'
+            #translateLabel: true
+            #isVisible: #hasJava
+            #value: #openAppletViewer
+            #enabled: #hasJavaAndSelection
+          )
+         #(#MenuItem
+            #label: 'Image Inspector'
+            #translateLabel: true
+            #value: #openImageInspector
+            #enabled: #hasSelection
+          )
+         #(#MenuItem
+            #label: 'Image Preview'
+            #translateLabel: true
+            #value: #openImagePreview
+            #enabled: #hasSelection
+          )
+         #(#MenuItem
+            #label: 'Image Editor'
+            #translateLabel: true
+            #value: #openImageEditor
+            #enabled: #hasSelection
+          )
+         #(#MenuItem
+            #label: 'MP3 Player'
+            #translateLabel: true
+            #isVisible: #hasMP3Player
+            #value: #openMP3Player
+            #enabled: #hasMP3PlayerAndSelection
+          )
+         #(#MenuItem
+            #label: 'ZipFile Tool'
+            #translateLabel: true
+            #value: #openZipTool
+            #enabled: #hasZipFileSelected
+          )
+         #(#MenuItem
+            #label: 'Slide Show'
+            #translateLabel: true
+            #isVisible: #hasSlideShow
+            #value: #openSlideShow
+            #enabled: #currentFilesAreInSameDirectory
+          )
+         #(#MenuItem
+            #label: 'File Differences...'
+            #translateLabel: true
+            #value: #openDiffView
+            #enabled: #hasSelection
+          )
+         #(#MenuItem
+            #label: 'Find Duplicate Files'
+            #translateLabel: true
+            #value: #fileFindDuplicates
+          )
+         #(#MenuItem
+            #label: 'Find All Duplicate Files (Recursive)'
+            #translateLabel: true
+            #value: #fileFindAllDuplicates
+            #enabled: #hasSelection
+          )
+         #(#MenuItem
+            #label: 'Find a File...'
+            #translateLabel: true
+            #value: #fileFindFile
+          )
+         #(#MenuItem
+            #label: 'Hex Dump'
+            #translateLabel: true
+            #value: #fileHexDump
+            #enabled: #hasSelection
+          )
+         )
+        nil
+        nil
+      )
+! !
+
+!FileBrowserV2 methodsFor:'actions'!
+
+changeFileBrowserTitleTo:aString
+
+    |string|
+
+    string := 'FileBrowser ', aString.
+    self window label:string.
+!
+
+doSpawn
+
+    self saveRuntimeAspectValues.
+    self class openWithAspects:aspects withExtent:self builder window extent.
+!
+
+hideFilenameEntryField
+    self filenameEntryFieldVisibleHolder value:false.
+!
+
+hideToolbar
+    self toolBarVisibleHolder value:false.
+! !
+
+!FileBrowserV2 methodsFor:'aspects'!
+
+fileEntryFieldHolder
+
+    fileEntryFieldHolder isNil ifTrue:[
+        fileEntryFieldHolder := ValueHolder new.
+        fileEntryFieldHolder addDependent:self.
+    ].
+    ^ fileEntryFieldHolder.
+! !
+
+!FileBrowserV2 methodsFor:'change & update'!
+
+update:something with:aParameter from:changedObject
+
+
+    changedObject == self fileEntryFieldHolder ifTrue:[
+        (fileEntryFieldHolder value asFilename exists) ifFalse:[^ self].
+        self currentFileNameHolder value:(OrderedCollection with:(fileEntryFieldHolder value asFilename)) withoutNotifying:self.
+    ].
+    changedObject == self currentFileNameHolder ifTrue:[
+        | files newDir|
+        files := self currentFileNameHolder value.
+        
+        (files isEmpty) ifTrue:[
+            self fileEntryFieldHolder value:nil withoutNotifying:self.
+            self hasSelection value:false.
+        ] ifFalse:[
+            self hasSelection value:true.
+            files size == 1 ifTrue:[
+                self fileEntryFieldHolder value:(files first) withoutNotifying:self.    
+            ] ifFalse:[
+                self fileEntryFieldHolder value:self getBestFile withoutNotifying:self.
+            ].
+        ].
+        " do not return here because the AbstractFileBrowserComponent have to do something
+          for every application "  
+"/        ^ self.
+    ].
+    (changedObject == self toolBarVisibleHolder 
+    or:[changedObject == self filenameEntryFieldVisibleHolder]) ifTrue:[
+        self updateToolVisibility.
+        ^ self.
+    ].
+
+    ^ super update:something with:aParameter from:changedObject.
+!
+
+updateToolVisibility
+    |builder toolBar filenameEntryField vPanel topOffset visible d|
+
+    builder := self builder.
+
+    topOffset := 0.
+    visible := self toolBarVisibleHolder value.
+    visible ifTrue:[
+        toolBar := builder componentAt:#ToolbarBox.
+        topOffset := topOffset + toolBar height.
+    ].
+
+    visible := self filenameEntryFieldVisibleHolder value.
+    visible ifTrue:[
+        filenameEntryField := builder componentAt:#FilenameEntryFieldBox.
+        d := filenameEntryField layout bottomOffset - filenameEntryField layout topOffset.
+        filenameEntryField layout topOffset:topOffset bottomOffset:topOffset + d.
+        topOffset := topOffset + filenameEntryField height.
+        filenameEntryField container notNil ifTrue:[
+            filenameEntryField containerChangedSize.
+        ].
+    ].
+
+    vPanel := builder componentAt:#BrowserBox.
+    vPanel layout topOffset:topOffset+1.
+    vPanel container notNil ifTrue:[
+        vPanel containerChangedSize.
+    ].
+! !
+
+!FileBrowserV2 methodsFor:'menu'!
+
+canBack
+
+    ^ self dirHistory canBack.
+!
+
+canForward
+
+    ^ self dirHistory canForward.
+!
+
+menuFileHistory
+    "initialize the file history menu
+    "
+    <resource: #programMenu >
+
+    |menu hist text removeItem removeCol|
+
+    menu := Menu new.
+    menu receiver:self.
+
+    hist := self fileHistory.
+    hist isEmpty ifTrue:[^ nil].
+    text := LabelAndIcon icon:(self class clearHistoryIcon) string:'Clear File History'.
+    removeCol := OrderedCollection new.
+    hist do:[:aFileItem|
+        aFileItem fileName exists ifTrue:[
+            menu addItem:(MenuItem label: aFileItem fileName asString value:[
+                self currentFileNameHolder value:(OrderedCollection with:(aFileItem fileName)).
+                self openApplByFileItem:aFileItem
+            ]).
+        ] ifFalse:[
+            removeCol add:aFileItem.
+        ]
+    ].
+    "/ remove all not existing history entries
+    removeCol do:[ : el |
+        hist remove:el.
+    ].
+    removeItem := MenuItem label:text value:[
+        self fileHistory removeAll.
+        self enableFileHistory value:false.
+    ].
+    menu addItem:(MenuItem label:'-').
+    menu addItem:removeItem.
+    ^ menu
+! !
+
+!FileBrowserV2 methodsFor:'startup & release'!
+
+hideFilenameEntryFieldButtonCreated:aButton
+
+    aButton passiveLevel:(MenuPanel defaultLevel). 
+    aButton activeLevel:-1.
+    aButton backgroundColor:(MenuPanel defaultBackgroundColor).
+!
+
+hideToolBarButtonCreated:aButton
+
+    aButton passiveLevel:(MenuPanel defaultLevel). 
+    aButton activeLevel:-1.
+    aButton backgroundColor:(MenuPanel defaultBackgroundColor).
+!
+
+initialize
+
+    self masterApplication:nil.
+!
+
+makeDependent
+
+    self currentFileNameHolder addDependent:self.
+    self notifyChannel addDependent:self.
+    self viewNoteBookApplicationHolder addDependent:self.
+    self filenameEntryFieldVisibleHolder addDependent:self.
+    self toolBarVisibleHolder addDependent:self.
+!
+
+postBuildPathField:aWidget
+    "
+        set the pramters that not can be changed in the window spec
+    "
+
+    |sClr lClr|
+
+    aWidget level:-1.
+
+"/    sClr := aWidget shadowColor.
+"/    lClr := aWidget lightColor.
+"/    sClr := (self builder componentAt:#ToolBar) shadowColor.
+"/    lClr := (self builder componentAt:#ToolBar) lightColor.
+
+"/    aWidget backgroundColor:(aWidget superView viewBackground).
+"/    aWidget shadowColor:sClr.
+!
+
+postBuildPathViewBox:aWidget
+
+    aWidget backgroundColor:(MenuPanel defaultBackgroundColor).
+!
+
+postBuildWith:aBuilder
+
+    super postBuildWith:aBuilder.
+    self updateToolVisibility
+!
+
+postOpenWith:aBuilder
+
+    self currentFileNameHolder changed.
+    self showDirectoryTreeHolder changed.
+    self viewNoteBookApplicationHolder changed.
+    ^ super postOpenWith:aBuilder
+!
+
+release
+
+    self saveRuntimeAspectValues.
+    ^ super release
+! !
+
+!FileBrowserV2 class methodsFor:'documentation'!
+
+version
+    ^ '$Header: /cvs/stx/stx/libtool/FileBrowserV2.st,v 1.1 2002-09-25 07:59:46 penk Exp $'
+! !
+
+FileBrowserV2 initialize!
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FileBrowserV2PanelView.st	Wed Sep 25 10:00:32 2002 +0200
@@ -0,0 +1,194 @@
+"
+ COPYRIGHT (c) 2002 by eXept Software AG 
+	      All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice.   This software may not
+ be provided or otherwise made available to, or used by, any
+ other person.  No title to or ownership of the software is
+ hereby transferred.
+
+
+"
+
+"{ Package: 'stx:libtool' }"
+
+VariablePanel subclass:#FileBrowserV2PanelView
+	instanceVariableNames:'whichView visibilityHolder oldOrigin oldCorner'
+	classVariableNames:'BarHeight'
+	poolDictionaries:''
+	category:'Interface-Tools-File'
+!
+
+!FileBrowserV2PanelView class methodsFor:'documentation'!
+
+copyright
+"
+ COPYRIGHT (c) 2002 by eXept Software AG 
+	      All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice.   This software may not
+ be provided or otherwise made available to, or used by, any
+ other person.  No title to or ownership of the software is
+ hereby transferred.
+
+
+"
+!
+
+documentation
+
+"
+    copy of the Panel from CBrowser , if a better HorizontalPanel and VerticalPanel is available
+    the new version can be used here
+"
+! !
+
+!FileBrowserV2PanelView methodsFor:'accessing'!
+
+visible:aState
+    |view1 view2 state|
+
+    state := aState ? true.
+
+    (state == self isVisible or:[subViews size ~~ 2]) ifTrue:[
+        ^ self
+    ].
+
+    view1 := subViews at:1.
+    view2 := subViews at:2.
+
+    state ifTrue:[
+        "
+        MAKE VISIBLE
+        "
+        barHeight := BarHeight.
+        view1 origin:0.0@0.0   corner:oldCorner.
+        view2 origin:oldOrigin corner:1.0@1.0.
+        self  resizeSubviews.
+    ] ifFalse:[
+        "
+        MAKE INVISIBLE
+        "
+        BarHeight := barHeight.
+        barHeight := 0.
+        oldCorner := view1 relativeCorner.
+        oldOrigin := view2 relativeOrigin.
+
+        orientation == #vertical ifTrue:[
+            whichView == #first ifTrue:[
+                view1 origin:0.0@0.0 corner:1.0@0.0.
+                view2 origin:0.0@0.0 corner:(view2 corner).
+            ] ifFalse:[
+                view1 origin:0.0@0.0 corner:1.0@1.0.
+                view2 origin:0.0@1.0 corner:(view2 corner).
+            ].
+        ] ifFalse:[
+            whichView == #first ifTrue:[
+                view1 origin:0.0@0.0 corner:0.0@1.0.
+                view2 origin:0.0@0.0 corner:1.0@1.0.
+            ] ifFalse:[
+                view1 origin:0.0@0.0 corner:1.0@1.0.
+                view2 origin:1.0@0.0 corner:1.0@1.0.
+            ]
+        ]
+    ].
+    visibilityHolder notNil ifTrue:[visibilityHolder value:state]
+!
+
+whichView
+    "return the value of the instance variable 'whichView' (automatically generated)"
+
+    ^ whichView
+!
+
+whichView:something
+    "set the value of the instance variable 'whichView' (automatically generated)"
+
+    whichView := something.
+! !
+
+!FileBrowserV2PanelView methodsFor:'accessing mvc'!
+
+visibilityHolder
+    ^ visibilityHolder
+!
+
+visibilityHolder:aHolder
+    visibilityHolder removeDependent:self.
+
+    (visibilityHolder := aHolder) notNil ifTrue:[
+        visibilityHolder addDependent:self.
+
+        realized ifTrue:[
+            self visible:(visibilityHolder value)
+        ]
+    ]
+! !
+
+!FileBrowserV2PanelView methodsFor:'actions'!
+
+toggleVisibility
+
+    self visible:(self isVisible not)
+! !
+
+!FileBrowserV2PanelView methodsFor:'change & update'!
+
+update:what with:aPara from:chgObj
+
+    chgObj == visibilityHolder ifTrue:[
+	^ self visible:(chgObj value)
+    ].
+    ^ super update:what with:aPara from:chgObj
+
+! !
+
+!FileBrowserV2PanelView methodsFor:'initialization'!
+
+destroy
+    visibilityHolder removeDependent:self.
+    super destroy
+!
+
+initialize
+    orientation := #vertical.
+    whichView   := #first.
+
+    super initialize
+!
+
+realize
+    super realize.
+
+    visibilityHolder notNil ifTrue:[
+        self visible:(visibilityHolder value)
+    ]
+! !
+
+!FileBrowserV2PanelView methodsFor:'queries'!
+
+anyNonRelativeSubviews
+    "return true, if any of my subviews has no relative origin/extent"
+
+    "/ cg asking ca: "whats the reason for this ?"
+    "/ ^ subViews notNil
+    ^ super anyNonRelativeSubviews.
+!
+
+isVisible
+    ^ barHeight ~~ 0
+!
+
+specClass
+    ^ FileBrowserV2UISpecifications panelSpecClass
+! !
+
+!FileBrowserV2PanelView class methodsFor:'documentation'!
+
+version
+    ^ '$Header: /cvs/stx/stx/libtool/FileBrowserV2PanelView.st,v 1.1 2002-09-25 07:58:30 penk Exp $'
+! !
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FileBrowserV2Tests.st	Wed Sep 25 10:00:32 2002 +0200
@@ -0,0 +1,116 @@
+"{ Package: 'stx:libtool' }"
+
+TestCase subclass:#FileBrowserV2Tests
+	instanceVariableNames:''
+	classVariableNames:''
+	poolDictionaries:''
+	category:'Interface-Tools-File'
+!
+
+!FileBrowserV2Tests class methodsFor:'documentation'!
+
+documentation
+"
+    documentation to be added.
+
+    [author:]
+        Christian Penk (penk@bierfix)
+
+    [instance variables:]
+
+    [class variables:]
+
+    [see also:]
+
+"
+!
+
+history
+    "Created: / 31.7.2002 / 11:59:23 / penk"
+! !
+
+!FileBrowserV2Tests methodsFor:'initialize / release'!
+
+setUp
+    "common setup - invoked before testing"
+
+    super setUp
+!
+
+tearDown
+    "common cleanup - invoked after testing"
+
+    super tearDown
+! !
+
+!FileBrowserV2Tests methodsFor:'tests'!
+
+testFileItem
+    "Just a demonstration testCase.
+     Double click on the TestCase class or open a TestRunner to see me checking...
+     - please add more methods like this..."
+
+    | file item|
+
+    file := Filename homeDirectory construct:'work/stx/doc/online/english/index.html'.
+    file exists ifTrue:[
+        item := DirectoryContentsBrowser itemClass with:file.
+        self should:(item mimeType = 'text/html').
+    ].
+
+    "
+     self run:#testFileItem
+    "
+!
+
+testHardLink
+    "Just a demonstration testCase.
+     Double click on the TestCase class or open a TestRunner to see me checking...
+     - please add more methods like this..."
+
+    |browser|
+
+    browser := FileBrowserV2 new.
+    
+    self should: ( browser isKindOf:AbstractFileBrowser ).
+    self should: ( browser respondsTo:#newHardLink ).
+    
+"/    self should: [ o at:0 ] raise:Error.
+
+    "
+     self run:#testHardLink
+    "
+!
+
+testHistory
+    "Just a demonstration testCase.
+     Double click on the TestCase class or open a TestRunner to see me checking...
+     - please add more methods like this..."
+
+    |history item1 item2 item3|
+
+    history := AbstractFileBrowser filenameHistoryClass new.
+    item1 := DirectoryContentsBrowser itemClass with:(Filename homeDirectory construct:'.bashrc').    
+    item2 := DirectoryContentsBrowser itemClass with:(Filename homeDirectory construct:'home').    
+    item3 := DirectoryContentsBrowser itemClass with:(Filename homeDirectory construct:'.bashrc').    
+    
+    self should: (item1 = item3).
+    history add:item1.
+    self assert: ( history size == 1 ).
+    history add:item2.
+    self assert: ( history size == 2 ).
+    history add:item3.
+    self assert: ( history size == 2 ).
+    
+"/    self should: [ o at:0 ] raise:Error.
+
+    "
+     self run:#testHistory
+    "
+! !
+
+!FileBrowserV2Tests class methodsFor:'documentation'!
+
+version
+    ^ '$Header: /cvs/stx/stx/libtool/FileBrowserV2Tests.st,v 1.1 2002-09-25 07:58:41 penk Exp $'
+! !
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FileBrowserV2UISpecifications.st	Wed Sep 25 10:00:32 2002 +0200
@@ -0,0 +1,551 @@
+"
+ COPYRIGHT (c) 2002 by eXept Software AG 
+	      All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice.   This software may not
+ be provided or otherwise made available to, or used by, any
+ other person.  No title to or ownership of the software is
+ hereby transferred.
+
+
+"
+
+"{ Package: 'stx:libtool' }"
+
+Object subclass:#FileBrowserV2UISpecifications
+	instanceVariableNames:''
+	classVariableNames:''
+	poolDictionaries:''
+	category:'Interface-Tools-File'
+!
+
+VariablePanelSpec subclass:#PanelSpec
+	instanceVariableNames:'whichView orientation visibility'
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:FileBrowserV2UISpecifications
+!
+
+!FileBrowserV2UISpecifications class methodsFor:'documentation'!
+
+copyright
+"
+ COPYRIGHT (c) 2002 by eXept Software AG 
+	      All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice.   This software may not
+ be provided or otherwise made available to, or used by, any
+ other person.  No title to or ownership of the software is
+ hereby transferred.
+
+
+"
+!
+
+documentation
+"
+    copy of the Panel from CBrowser , if a better HorizontalPanel and VerticalPanel is available
+    the new version can be used here
+"
+! !
+
+!FileBrowserV2UISpecifications class methodsFor:'classAccess'!
+
+panelSpecClass
+
+    ^ PanelSpec
+! !
+
+!FileBrowserV2UISpecifications class methodsFor:'interface specs'!
+
+listSpec
+    "This resource specification was automatically generated
+     by the UIPainter of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the UIPainter may not be able to read the specification."
+
+    "
+     UIPainter new openOnClass:FileBrowserV2UISpecifications andSelector:#listSpec
+    "
+
+    <resource: #canvas>
+
+    ^ 
+     #(#FullSpec
+        #name: #listSpec
+        #window: 
+       #(#WindowSpec
+          #label: 'Graphs'
+          #name: 'Graphs'
+          #layout: #(#LayoutFrame 7 0 129 0 441 0 316 0)
+          #level: 0
+          #min: #(#Point 10 10)
+          #max: #(#Point 1280 1024)
+          #bounds: #(#Rectangle 7 129 442 317)
+          #usePreferredExtent: false
+          #returnIsOKInDialog: true
+          #escapeIsCancelInDialog: true
+        )
+        #component: 
+       #(#SpecCollection
+          #collection: #(
+           #(#HierarchicalListViewSpec
+              #name: 'HierarchicalListModel'
+              #layout: #(#LayoutFrame 225 0 7 0 398 0 79 0)
+              #hasHorizontalScrollBar: true
+              #hasVerticalScrollBar: true
+              #miniScrollerHorizontal: true
+              #highlightMode: #line
+            )
+           #(#LabelSpec
+              #label: 'HierarchicalList'
+              #name: 'HierarchicalListLabel'
+              #layout: #(#Point 252 15)
+              #style: #(#FontDescription #helvetica #medium #roman 10)
+              #resizeForLabel: true
+              #adjust: #left
+              #canUIDrag: false
+            )
+           #(#SelectionInListModelViewSpec
+              #name: 'SelectionInListModel'
+              #layout: #(#LayoutFrame 6 0 7 0 179 0 79 0)
+              #hasHorizontalScrollBar: true
+              #hasVerticalScrollBar: true
+              #miniScrollerHorizontal: true
+              #highlightMode: #line
+            )
+           #(#LabelSpec
+              #label: 'SelectionInList'
+              #name: 'SelectionInListLabel'
+              #layout: #(#Point 33 15)
+              #style: #(#FontDescription #helvetica #medium #roman 10)
+              #resizeForLabel: true
+              #adjust: #left
+              #canUIDrag: false
+            )
+           #(#ListModelViewSpec
+              #name: 'ListModel'
+              #layout: #(#LayoutFrame 6 0 100 0 179 0 172 0)
+              #hasHorizontalScrollBar: true
+              #hasVerticalScrollBar: true
+              #miniScrollerHorizontal: true
+            )
+           #(#LabelSpec
+              #label: 'ListModel'
+              #name: 'ListModelLabel'
+              #layout: #(#Point 33 109)
+              #style: #(#FontDescription #helvetica #medium #roman 10)
+              #resizeForLabel: true
+              #adjust: #left
+              #canUIDrag: false
+            )
+           )
+         
+        )
+      )
+!
+
+othersSpec
+    "This resource specification was automatically generated
+     by the UIPainter of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the UIPainter may not be able to read the specification."
+
+    "
+     UIPainter new openOnClass:FileBrowserV2UISpecifications andSelector:#othersSpec
+    "
+
+    <resource: #canvas>
+
+    ^ 
+     #(#FullSpec
+        #name: #othersSpec
+        #window: 
+       #(#WindowSpec
+          #label: 'Panel Specs'
+          #name: 'Panel Specs'
+          #layout: #(#LayoutFrame 119 0 66 0 536 0 215 0)
+          #level: 0
+          #min: #(#Point 10 10)
+          #max: #(#Point 1280 1024)
+          #bounds: #(#Rectangle 119 66 537 216)
+          #usePreferredExtent: false
+          #returnIsOKInDialog: true
+          #escapeIsCancelInDialog: true
+        )
+        #component: 
+       #(#SpecCollection
+          #collection: #(
+           #(#LabelSpec
+              #label: 'Wrapper'
+              #name: 'WrapperLabel'
+              #layout: #(#Point 9 6)
+              #style: #(#FontDescription #helvetica #medium #roman 10)
+              #resizeForLabel: true
+              #adjust: #left
+              #canUIDrag: false
+            )
+           #(#'FileBrowserV2UISpecifications::WrapperSpec'
+              #name: 'Wrapper'
+              #layout: #(#LayoutFrame 6 0 26 0 179 0 98 0)
+            )
+           #(#LabelSpec
+              #label: 'Panel'
+              #name: 'PanelLabel'
+              #layout: #(#Point 201 6)
+              #style: #(#FontDescription #helvetica #medium #roman 10)
+              #resizeForLabel: true
+              #adjust: #left
+              #canUIDrag: false
+            )
+
+           #(#'FileBrowserV2UISpecifications::PanelSpec'
+              #name: 'Panel'
+              #layout: #(#LayoutFrame 198 0 26 0 376 0 98 0)
+              #level: 0
+              #whichView: #first
+              #orientation: #vertical
+              #component: 
+             #(#SpecCollection
+                #collection: #(
+                 #(#LabelSpec
+                    #label: 'A'
+                    #name: 'Label1'
+                    #layout: #(#LayoutFrame 0 0.0 0 0.0 0 0.5 0 1.0)
+                    #level: 2
+                    #canUIDrag: false
+                  )
+                 #(#LabelSpec
+                    #label: 'B'
+                    #name: 'Label2'
+                    #layout: #(#LayoutFrame 0 0.5 0 0.0 0 1.0 0 1.0)
+                    #level: 2
+                    #canUIDrag: false
+                  )
+                 )
+               
+              )
+            )
+           )
+         
+        )
+      )
+! !
+
+!FileBrowserV2UISpecifications class methodsFor:'setup'!
+
+setup
+"
+FileBrowserV2UISpecifications setup.
+
+"
+    |listSpec othersSpec|
+
+    UISelectionPanel galleryClass removeUserSpecWithLabel:'Graphs'.
+    UISelectionPanel galleryClass removeUserSpecWithLabel:'Clocks etc.'.
+    UISelectionPanel galleryClass removeUserSpecWithLabel:'Business Graphics'.
+    UISelectionPanel galleryClass removeUserSpecWithLabel:'C-Lists'.
+    UISelectionPanel galleryClass removeUserSpecWithLabel:'C-Others'.
+
+    listSpec := ValueHolder new.
+    listSpec value:(self listSpec).
+
+    UISelectionPanel galleryClass addUserSpecHolder:listSpec
+                label:'C-Lists'.
+
+    othersSpec := ValueHolder new.
+    othersSpec value:(self othersSpec).
+
+    UISelectionPanel galleryClass addUserSpecHolder:othersSpec
+                label:'C-Others'.
+! !
+
+!FileBrowserV2UISpecifications::PanelSpec class methodsFor:'interface - painter'!
+
+addBindingsTo:env for:anInstance channel:aChannel 
+    "add bindings as required to allow the GUI Painter to operate on an instance of me"
+
+    super addBindingsTo:env for:anInstance channel:aChannel.
+
+    self adaptApects:#( visibility ) to:env for:anInstance channel:aChannel converter:#symbolOrNil.
+    self adaptApects:#( whichView orientation ) to:env for:anInstance channel:aChannel.
+
+    env at:#whichViewList put:#( #first #last ) asValue.
+    env at:#orientationList put:#( #horizontal #vertical ) asValue.
+
+
+
+! !
+
+!FileBrowserV2UISpecifications::PanelSpec class methodsFor:'interface - specs'!
+
+detailsEditSpec
+    "This resource specification was automatically generated
+     by the UIPainter of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the UIPainter may not be able to read the specification."
+
+    "
+     UIPainter new openOnClass:FileBrowserV2UISpecifications::PanelSpec andSelector:#detailsEditSpec
+    "
+
+    <resource: #canvas>
+
+    ^ 
+     #(#FullSpec
+        #name: #detailsEditSpec
+        #window: 
+       #(#WindowSpec
+          #label: 'Panel Detail Spec'
+          #name: 'Panel Detail Spec'
+          #layout: #(#LayoutFrame 5 0 66 0 442 0 341 0)
+          #level: 0
+          #min: #(#Point 10 10)
+          #max: #(#Point 1160 870)
+          #bounds: #(#Rectangle 5 66 443 342)
+          #usePreferredExtent: false
+          #returnIsOKInDialog: true
+          #escapeIsCancelInDialog: true
+        )
+        #component: 
+       #(#SpecCollection
+          #collection: #(
+           #(#UISubSpecification
+              #name: 'SubSpecification1'
+              #layout: #(#LayoutFrame 1 0 0 0.0 0 1.0 183 0)
+              #majorKey: #ViewSpec
+              #minorKey: #detailsEditSpec
+            )
+           #(#FramedBoxSpec
+              #label: 'Visibility'
+              #name: 'FramedBox1'
+              #layout: #(#LayoutFrame 0 0.0 177 0 0 1.0 261 0)
+              #labelPosition: #topLeft
+              #translateLabel: true
+              #component: 
+             #(#SpecCollection
+                #collection: #(
+                 #(#LabelSpec
+                    #label: 'orientation:'
+                    #name: 'orientation'
+                    #layout: #(#AlignmentOrigin 85 0 13 0 1 0.5)
+                    #activeHelpKey: #borderWidth
+                    #resizeForLabel: true
+                    #adjust: #left
+                  )
+                 #(#ComboListSpec
+                    #name: 'orientationList'
+                    #layout: #(#LayoutFrame 85 0 2 0 194 0 24 0)
+                    #model: #orientation
+                    #comboList: #orientationList
+                    #useIndex: false
+                  )
+                 #(#LabelSpec
+                    #label: 'which:'
+                    #name: 'visibilityOf'
+                    #layout: #(#AlignmentOrigin 248 0 13 0 1 0.5)
+                    #activeHelpKey: #borderWidth
+                    #resizeForLabel: true
+                    #adjust: #left
+                  )
+                 #(#ComboListSpec
+                    #name: 'whichViewList'
+                    #layout: #(#LayoutFrame 247 0 2 0 0 1.0 24 0)
+                    #model: #whichView
+                    #comboList: #whichViewList
+                    #useIndex: false
+                  )
+                 #(#InputFieldSpec
+                    #name: 'visibility'
+                    #layout: #(#LayoutFrame 85 0 29 0 0 1.0 51 0)
+                    #activeHelpKey: #canvas
+                    #model: #visibility
+                    #group: #inputGroup
+                    #acceptChannel: #acceptChannel
+                    #modifiedChannel: #modifiedChannel
+                    #acceptOnPointerLeave: false
+                  )
+                 #(#LabelSpec
+                    #label: 'visibility:'
+                    #name: 'visibilityLabel'
+                    #layout: #(#AlignmentOrigin 85 0 40 0 1 0.5)
+                    #resizeForLabel: true
+                  )
+                 )
+               
+              )
+            )
+           )
+         
+        )
+      )
+! !
+
+!FileBrowserV2UISpecifications::PanelSpec methodsFor:'accessing'!
+
+orientation
+    "return the value of the instance variable 'orientation' (automatically generated)"
+
+    ^ orientation ? #vertical
+!
+
+orientation:something
+    "set the value of the instance variable 'orientation' (automatically generated)"
+    something notNil ifTrue:[
+	orientation := something asSymbol
+    ] ifFalse:[
+	orientation := something.
+    ]
+!
+
+visibility
+    "return the value of the instance variable 'orientation' (automatically generated)"
+
+    ^ visibility
+!
+
+visibility:something
+    "set the value of the instance variable 'visibility' (automatically generated)"
+
+    visibility := something.
+!
+
+whichView
+    "return the value of the instance variable 'whichView' (automatically generated)"
+
+    ^ whichView ? #first
+!
+
+whichView:something
+    "set the value of the instance variable 'whichView' (automatically generated)"
+
+    whichView := something.
+! !
+
+!FileBrowserV2UISpecifications::PanelSpec methodsFor:'building'!
+
+aspectSelectors
+    "add more aspect selectors
+    "
+    |more|
+
+    more := super aspectSelectors.
+    visibility notNil ifTrue:[more add:visibility].
+  ^ more
+
+!
+
+setAttributesIn:aView with:aBuilder
+    "set my attributes to aView
+    "
+    super setAttributesIn:aView with:aBuilder.
+
+    aView        whichView:(self whichView).
+    aView      orientation:(self orientation).
+    aView visibilityHolder:(self getBindingIn:aBuilder binding:visibility).
+
+
+
+! !
+
+!FileBrowserV2UISpecifications::PanelSpec methodsFor:'computation'!
+
+recomputeHandlesIn:aPanel
+    |subs isVertical|
+
+    (subs := aPanel subViews) notNil ifTrue:[
+	isVertical := self isVertical.
+	^ subs 
+	    collect:
+		[:v | |rel|
+		    rel := v relativeCorner. 
+		    isVertical ifTrue:[ rel y] ifFalse:[ rel x ].
+		]
+    ].
+    ^ nil
+!
+
+setLayoutsInLayoutContainer:aPanel
+    |x y subs isVertical|
+
+    ((subs := aPanel subViews) notNil and:[subs size == handles size]) ifTrue:[
+	isVertical := self isVertical.
+	y := x := 0.0.
+	subs keysAndValuesDo:[:i :v|
+	    isVertical ifTrue:[
+		v relativeOrigin:(0.0 @ y).
+		y := handles at:i.
+		v relativeCorner:(1.0 @ y).
+	    ] ifFalse:[
+		v relativeOrigin:(x @ 0.0).
+		x := handles at:i.
+		v relativeCorner:(x @ 1.0).
+	    ]
+	]
+    ]
+!
+
+setupInitialLayoutFor:aView
+    |superView|
+
+    aView geometryLayout:nil.
+
+    (    aView relativeOrigin isNil 
+     or:[aView relativeExtent isNil 
+	 and:[aView relativeCorner isNil]]
+    ) ifTrue:[
+	superView := aView superView.
+
+	self isVertical ifTrue:[
+	    aView corner:0@0.
+	    aView origin:0.0@0.0.
+	    aView extent:1.0@0.3.
+	    superView notNil ifTrue:[
+		superView setupSubviews.
+		superView resizeSubviews.
+	    ]
+	] ifFalse:[
+	    aView origin:0.0@0.0.
+	    aView extent:0.3@1.0.
+	    superView notNil ifTrue:[
+		superView setupSubviews
+	    ]
+	]
+    ]
+! !
+
+!FileBrowserV2UISpecifications::PanelSpec methodsFor:'converting'!
+
+skippedInLiteralEncoding
+    |l|
+
+    l := super skippedInLiteralEncoding asOrderedCollection.
+    visibility isNil ifTrue:[l add:#visibility].
+  ^ l
+! !
+
+!FileBrowserV2UISpecifications::PanelSpec methodsFor:'queries'!
+
+isVertical
+    ^ self orientation == #vertical
+
+!
+
+viewClass
+    "return the corresponding view class of the spec"
+
+    ^ FileBrowserV2PanelView
+! !
+
+!FileBrowserV2UISpecifications class methodsFor:'documentation'!
+
+version
+    ^ '$Header: /cvs/stx/stx/libtool/FileBrowserV2UISpecifications.st,v 1.1 2002-09-25 07:59:55 penk Exp $'
+! !
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FileDialog.st	Wed Sep 25 10:00:32 2002 +0200
@@ -0,0 +1,885 @@
+"{ Package: 'stx:libtool' }"
+
+SimpleDialog subclass:#FileDialog
+	instanceVariableNames:'aspects treeBrowser enableBack enableDirectoryUp enableForward
+		enableHome directory pattern filterHolder initialText
+		cancelLabelHolder okLabelHolder startFilename result filterField
+		filenameField viewFiles'
+	classVariableNames:'LastFileSelectionDirectory'
+	poolDictionaries:''
+	category:'Interface-Tools-File'
+!
+
+!FileDialog class methodsFor:'documentation'!
+
+documentation
+"
+    documentation to be added.
+
+    [author:]
+        Martin Walser (martin@vercingetorix)
+
+    [instance variables:]
+
+    [class variables:]
+
+    [see also:]
+
+"
+!
+
+examples
+"
+  Starting the application:
+                                                                [exBegin]
+    FileDialog open
+
+                                                                [exEnd]
+
+  more examples to be added:
+                                                                [exBegin]
+    ... add code fragment for 
+    ... executable example here ...
+                                                                [exEnd]
+"
+!
+
+history
+    "Created: / 19.9.2002 / 13:05:28 / martin"
+! !
+
+!FileDialog class methodsFor:'instance creation'!
+
+requestDirectoryName:title default:aFileName ifFail:failBlock
+    "same as requestFileName, but only show directories"
+
+    ^ self  requestDirectoryName:title 
+            default:aFileName 
+            ok:nil 
+            abort:nil 
+            version:nil 
+            pattern:nil 
+            fromDirectory:nil 
+            ifFail:failBlock 
+            whenBoxCreatedEvaluate:nil.
+
+    "
+     Dialog
+        requestDirectoryName:'which directory ?' 
+        default:'/etc'
+        ifFail:'none'
+    "
+!
+
+requestDirectoryName:title default:aFileName ok:okText abort:abortText version:versionSymbol pattern:pattern fromDirectory:aDirectoryPath ifFail:failBlock whenBoxCreatedEvaluate:boxCreatedCallback
+    "same as requestFileName, but only show directories"
+
+    |enteredFileName instance defaultNm defaultDir enteredFileNameString defaultFile|
+
+    defaultNm := aFileName.
+    defaultDir := aDirectoryPath.
+    defaultDir isNil ifTrue:[
+        defaultNm notNil ifTrue:[
+            defaultDir := defaultNm asFilename directory.
+        ] ifFalse:[
+            defaultDir := FileSelectionBox lastFileSelectionDirectory.
+            defaultDir isNil ifTrue:[
+                defaultDir := Filename currentDirectory asAbsoluteFilename.        
+            ].
+        ]
+    ].
+    defaultDir := defaultDir asFilename.
+    [defaultDir exists not] whileTrue:[
+        defaultDir := defaultDir directory.
+    ].
+    defaultNm isNil ifTrue:[
+        defaultFile := defaultDir.
+    ] ifFalse:[
+        defaultFile := defaultNm asFilename.
+    ].
+    instance := self new.
+"/    defaultDir notNil ifTrue:[instance directory:(defaultDir asFilename)].
+    defaultDir notNil ifTrue:[instance directory:defaultFile].
+    instance startFilename:defaultFile.
+    instance initialText:title.
+    instance pattern:((pattern isNil or:[pattern isEmpty]) ifTrue:['*'] ifFalse:[pattern]).
+    instance okLabelHolder value:okText.
+    instance cancelLabelHolder value:abortText.
+    instance viewFiles:false.
+
+    instance allButOpenInterface:#windowSpec.
+    boxCreatedCallback notNil ifTrue:[boxCreatedCallback value:instance].
+    instance openWindowModal.
+
+    enteredFileNameString := instance result.
+    enteredFileNameString isNil ifTrue:[
+        ^ failBlock value
+    ].
+    enteredFileName := enteredFileNameString asFilename.
+    enteredFileNameString := enteredFileName asString.
+    (enteredFileName notNil 
+    and:[enteredFileNameString notEmpty]) ifTrue:[
+        versionSymbol isNil ifTrue:[ ^ enteredFileNameString].
+        versionSymbol == #mustBeNew ifTrue:[
+            "/ file may not exist
+            enteredFileName exists ifTrue:[^ ''].
+        ].
+        versionSymbol == #new ifTrue:[
+            "/ file may not exist
+            enteredFileName exists ifTrue:[
+                (Dialog confirm:(self classResources string:'''%1'' exists.\\Continue anyway ?' with:enteredFileNameString) withCRs)
+                    ifFalse:[^ ''].
+            ].
+        ].
+        versionSymbol == #mustBeOld ifTrue:[
+            enteredFileName exists ifFalse:[^ ''].
+        ].
+        versionSymbol == #old ifTrue:[
+            "/ file may not exist
+            enteredFileName exists ifFalse:[
+                (self confirm:(self classResources string:'''%1'' does not exist yet.\\Continue anyway ?' with:enteredFileNameString) withCRs)
+                ifFalse:[^ ''].
+            ].
+        ].
+        FileSelectionBox lastFileSelectionDirectory:(enteredFileNameString).
+    ].
+    ^ enteredFileNameString
+
+    "
+     FileDialog
+        requestDirectoryName:'which directory ?' 
+        default:'/etc'
+        ifFail:nil
+    "
+!
+
+requestFileName:titleString default:defaultName ok:okText abort:abortText pattern:pattern fromDirectory:aDirectoryPathOrNil whenBoxCreatedEvaluate:boxCreatedCallback
+
+    ^ self  requestFileName:titleString 
+            default:defaultName 
+            ok:okText 
+            abort:abortText 
+            version:nil 
+            ifFail:nil 
+            pattern:pattern 
+            fromDirectory:aDirectoryPathOrNil 
+            whenBoxCreatedEvaluate:boxCreatedCallback
+!
+
+requestFileName:titleString default:defaultName ok:okText abort:abortText version:versionSymbol ifFail:failBlock pattern:pattern fromDirectory:aDirectoryPath whenBoxCreatedEvaluate:boxCreatedCallback
+    "launch a Dialog, which allows user to enter a filename.
+     The files presented initially are those in aDirectoryPathOrNil, or the
+     last fileBox directory (default: current directory) (if a nil path is given).
+     The box will show okText in its okButton, abortText in the abortButton.
+     The matchPattern is set to pattern initially.
+     Return the string, or nil if cancel was pressed
+     The version argument allows validation of the files existance;
+     it may be any of:
+        #mustBeNew      - fail (return empty string) if the file exists
+        #new            - confirm if the file exists
+        #mustBeOld      - fail if the file does not exist
+        #old            - confirm if the file does not exist
+        #any (other)    - no validation
+    "
+
+
+    | defaultDir defaultNm instance enteredFileName enteredFileNameString defaultFile|
+
+    defaultNm := defaultName.
+    defaultDir := aDirectoryPath.
+    defaultDir isNil ifTrue:[
+        defaultDir := FileSelectionBox lastFileSelectionDirectory.
+        defaultDir isNil ifTrue:[
+            defaultDir := Filename currentDirectory asAbsoluteFilename.        
+        ].
+    ].
+    defaultDir := defaultDir asFilename.
+    [defaultDir exists not] whileTrue:[
+        defaultDir := defaultDir directory.
+    ].
+    (defaultName notNil and:[defaultName asFilename withoutSuffix baseName ~= '*']) ifTrue:[
+        defaultFile := defaultDir construct:defaultName.
+    ] ifFalse:[
+        defaultFile := defaultDir.
+    ].
+    instance := self new.
+    defaultDir notNil ifTrue:[instance directory:(defaultDir asFilename)].
+    instance startFilename:defaultFile.
+    instance pattern:((pattern isNil or:[pattern isEmpty]) ifTrue:['*'] ifFalse:[pattern]).
+    instance initialText:titleString.
+    instance okLabelHolder value:okText.
+    instance cancelLabelHolder value:abortText.
+    instance viewFiles:true.
+
+    instance allButOpenInterface:#windowSpec.
+    boxCreatedCallback notNil ifTrue:[boxCreatedCallback value:instance].
+    instance openWindowModal.
+
+    enteredFileNameString := instance result.
+    enteredFileNameString isNil ifTrue:[
+        ^ failBlock value
+    ].
+    enteredFileName := enteredFileNameString asFilename.
+    enteredFileNameString := enteredFileName asString.
+    (enteredFileName notNil 
+    and:[enteredFileNameString notEmpty]) ifTrue:[
+        versionSymbol isNil ifTrue:[ ^ enteredFileNameString].
+        versionSymbol == #mustBeNew ifTrue:[
+            "/ file may not exist
+            enteredFileName exists ifTrue:[^ ''].
+        ].
+        versionSymbol == #new ifTrue:[
+            "/ file may not exist
+            enteredFileName exists ifTrue:[
+                (Dialog confirm:(self classResources string:'''%1'' exists.\\Continue anyway ?' with:enteredFileNameString) withCRs)
+                    ifFalse:[^ ''].
+            ].
+        ].
+        versionSymbol == #mustBeOld ifTrue:[
+            enteredFileName exists ifFalse:[^ ''].
+        ].
+        versionSymbol == #old ifTrue:[
+            "/ file may not exist
+            enteredFileName exists ifFalse:[
+                (self confirm:(self classResources string:'''%1'' does not exist yet.\\Continue anyway ?' with:enteredFileNameString) withCRs)
+                ifFalse:[^ ''].
+            ].
+        ].
+        FileSelectionBox lastFileSelectionDirectory:(enteredFileName directoryName).
+    ].
+    ^ enteredFileNameString
+!
+
+requestFileName:titleString default:defaultName version:versionSymbol ifFail:failBlock pattern:pattern fromDirectory:aDirectoryPathOrNil whenBoxCreatedEvaluate:boxCreatedCallback
+
+    ^ self  requestFileName:titleString 
+            default:defaultName 
+            ok:nil 
+            abort:nil 
+            version:versionSymbol 
+            ifFail:failBlock 
+            pattern:pattern 
+            fromDirectory:aDirectoryPathOrNil 
+            whenBoxCreatedEvaluate:boxCreatedCallback
+
+    "
+     FileDialog 
+        requestFileName:'enter a fileName:'
+        default:''
+        version:nil
+        ifFail:['none']
+        pattern:'*.conf'
+        fromDirectory:'/etc'
+        whenBoxCreatedEvaluate:nil.
+     Dialog 
+        requestFileName:'enter a fileName:'
+        default:''
+        version:nil
+        ifFail:['none']
+        pattern:'*.conf'
+        fromDirectory:'/etc'
+        whenBoxCreatedEvaluate:nil
+    "
+    "
+     FileDialog
+        requestFileName:'enter a fileName:'
+        default:''
+        version:#old 
+        ifFail:['none']   
+        pattern:'*.conf'
+        fromDirectory:'/etc'
+        whenBoxCreatedEvaluate:nil
+    "
+    "
+     FileDialog
+        requestFileName:'enter a fileName:'
+        default:''
+        version:#mustBeNew 
+        ifFail:['none']   
+        pattern:'*.conf'
+        fromDirectory:'/etc'
+        whenBoxCreatedEvaluate:nil
+    "
+! !
+
+!FileDialog class methodsFor:'accessing'!
+
+lastFileSelectionDirectory
+    "return the name of the directory used in the previous
+     fileSelection dialog. This will be used as default for the next dialog,
+     if no explicit path is specified (see requestFileName:* methods)"
+
+    |f|
+
+    LastFileSelectionDirectory notNil ifTrue:[
+        ((f := LastFileSelectionDirectory asFilename) exists 
+        and:[f isDirectory]) ifFalse:[
+            LastFileSelectionDirectory := nil.
+        ]
+    ].
+    ^ LastFileSelectionDirectory
+!
+
+lastFileSelectionDirectory:aDirectoryString
+    "set the name of the directory used in the previous
+     fileSelection dialog. This will be used as default for the next dialog,
+     if no explicit path is specified (see requestFileName:* methods)"
+
+    LastFileSelectionDirectory := aDirectoryString
+! !
+
+!FileDialog class methodsFor:'interface specs'!
+
+windowSpec
+    "This resource specification was automatically generated
+     by the UIPainter of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the UIPainter may not be able to read the specification."
+
+    "
+     UIPainter new openOnClass:FileDialog andSelector:#windowSpec
+     FileDialog new openInterface:#windowSpec
+     FileDialog open
+    "
+
+    <resource: #canvas>
+
+    ^ 
+     #(#FullSpec
+        #name: #windowSpec
+        #window: 
+       #(#WindowSpec
+          #label: 'FileDialog'
+          #name: 'FileDialog'
+          #min: #(#Point 10 10)
+          #max: #(#Point 1024 768)
+          #bounds: #(#Rectangle 16 42 416 442)
+        )
+        #component: 
+       #(#SpecCollection
+          #collection: #(
+           #(#MenuPanelSpec
+              #name: 'ToolBar1'
+              #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 30 0)
+              #tabable: true
+              #menu: #toolBarMenu
+              #textDefault: true
+            )
+           #(#SubCanvasSpec
+              #name: 'DirectoryTreeBrowser'
+              #layout: #(#LayoutFrame 0 0.0 30 0 0 1.0 -107 1)
+              #tabable: true
+              #hasHorizontalScrollBar: false
+              #hasVerticalScrollBar: false
+              #majorKey: #DirectoryTreeBrowser
+              #createNewApplication: true
+              #createNewBuilder: true
+              #postBuildCallback: #postBuildTreeBrowser:
+            )
+           #(#LabelSpec
+              #label: 'Filename:'
+              #name: 'FilenameLabel'
+              #layout: #(#LayoutFrame 3 0 -97 1 73 0 -77 1)
+              #translateLabel: true
+              #adjust: #left
+            )
+           #(#FilenameInputFieldSpec
+              #name: 'FilenameEntryField'
+              #layout: #(#LayoutFrame 70 0 -96 1 -10 1 -76 1)
+              #tabable: true
+              #model: #filenameHolder
+              #acceptOnPointerLeave: false
+              #postBuildCallback: #postBuildFileNameField:
+            )
+           #(#LabelSpec
+              #label: 'Filter:'
+              #name: 'FilterLabel'
+              #layout: #(#LayoutFrame 3 0 -70 1 67 0 -50 1)
+              #translateLabel: true
+              #adjust: #left
+            )
+           #(#InputFieldSpec
+              #name: 'FilterEntryField'
+              #layout: #(#LayoutFrame 70 0 -69 1 -10 1 -49 1)
+              #model: #filterHolder
+              #immediateAccept: true
+              #acceptOnReturn: true
+              #acceptOnTab: true
+              #acceptOnLostFocus: true
+              #acceptOnPointerLeave: false
+              #postBuildCallback: #postBuildFilterField:
+            )
+           #(#HorizontalPanelViewSpec
+              #name: 'ButtonPanel'
+              #layout: #(#LayoutFrame 0 0.0 -40 1 0 1 0 1)
+              #horizontalLayout: #spreadSpace
+              #verticalLayout: #center
+              #horizontalSpace: 3
+              #verticalSpace: 3
+              #reverseOrderIfOKAtLeft: true
+              #component: 
+             #(#SpecCollection
+                #collection: #(
+                 #(#ActionButtonSpec
+                    #label: 'Cancel'
+                    #name: 'cancelButton'
+                    #translateLabel: true
+                    #labelChannel: #cancelLabelHolder
+                    #tabable: true
+                    #model: #doCancel
+                    #extent: #(#Point 150 21)
+                  )
+                 #(#ActionButtonSpec
+                    #label: 'OK'
+                    #name: 'okButton'
+                    #translateLabel: true
+                    #labelChannel: #okLabelHolder
+                    #tabable: true
+                    #model: #doAccept
+                    #isDefault: true
+                    #extent: #(#Point 150 22)
+                  )
+                 )
+               
+              )
+            )
+           )
+         
+        )
+      )
+! !
+
+!FileDialog class methodsFor:'menu specs'!
+
+toolBarMenu
+    "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:FileDialog andSelector:#toolBarMenu
+     (Menu new fromLiteralArrayEncoding:(FileDialog toolBarMenu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #label: 'DirectoryUp'
+            #translateLabel: true
+            #isButton: true
+            #value: #doGoDirectoryUp
+            #activeHelpKey: #directoryUp
+            #enabled: #enableDirectoryUp
+            #labelImage: #(#ResourceRetriever #AbstractFileBrowser #upArrow20x20Icon)
+          )
+         #(#MenuItem
+            #label: '-'
+          )
+         #(#MenuItem
+            #label: 'Back'
+            #translateLabel: true
+            #isButton: true
+            #value: #doBack
+            #activeHelpKey: #directoryBack
+            #enabled: #enableBack
+            #submenuChannel: #menuDirHistoryBack
+            #labelImage: #(#ResourceRetriever #AbstractFileBrowser #leftArrow20x20PlusMenuIcon)
+          )
+         #(#MenuItem
+            #label: '-'
+          )
+         #(#MenuItem
+            #label: 'Forward'
+            #translateLabel: true
+            #isButton: true
+            #value: #doForward
+            #activeHelpKey: #directoryForward
+            #submenuChannel: #menuDirHistoryForward
+            #enabled: #enableForward
+            #labelImage: #(#ResourceRetriever #AbstractFileBrowser #rightArrowPlusMenu20x20Icon)
+          )
+         #(#MenuItem
+            #label: '-'
+          )
+         #(#MenuItem
+            #label: 'Home'
+            #translateLabel: true
+            #isButton: true
+            #value: #doGotoHomeDirectory
+            #activeHelpKey: #fileHome
+            #enabled: #enableHome
+            #labelImage: #(#ResourceRetriever #AbstractFileBrowser #goHomeIcon)
+          )
+         )
+        nil
+        nil
+      )
+! !
+
+!FileDialog methodsFor:'accessing'!
+
+directory
+    "return the value of the instance variable 'directory' (automatically generated)"
+
+    ^ directory
+!
+
+directory:something
+    "set the value of the instance variable 'directory' (automatically generated)"
+
+    directory := something.
+!
+
+initialText
+    "return the value of the instance variable 'initialText' (automatically generated)"
+
+    ^ initialText
+!
+
+initialText:something
+    "set the value of the instance variable 'initialText' (automatically generated)"
+
+    initialText := something.
+!
+
+pattern
+    "return the value of the instance variable 'pattern' (automatically generated)"
+
+    ^ pattern
+!
+
+pattern:something
+    "set the value of the instance variable 'pattern' (automatically generated)"
+
+    pattern := something.
+!
+
+result
+    "return the value of the instance variable 'result' (automatically generated)"
+
+    ^ result
+!
+
+result:something
+    "set the value of the instance variable 'result' (automatically generated)"
+
+    result := something.
+!
+
+startFilename
+    "return the value of the instance variable 'startFilename' (automatically generated)"
+
+    startFilename isNil ifTrue:[
+        startFilename := Filename currentDirectory asAbsoluteFilename.
+    ].
+    ^ startFilename
+!
+
+startFilename:something
+    "set the value of the instance variable 'startFilename' (automatically generated)"
+
+    startFilename := something.
+!
+
+viewFiles
+    "return the value of the instance variable 'viewFiles' (automatically generated)"
+
+    ^ viewFiles
+!
+
+viewFiles:something
+    "set the value of the instance variable 'viewFiles' (automatically generated)"
+
+    viewFiles := something.
+! !
+
+!FileDialog methodsFor:'aspects'!
+
+cancelLabelHolder
+    "automatically generated by UIPainter ..."
+
+    "*** the code below creates a default model when invoked."
+    "*** (which may not be the one you wanted)"
+    "*** Please change as required and accept it in the browser."
+    "*** (and replace this comment by something more useful ;-)"
+
+    cancelLabelHolder isNil ifTrue:[
+        cancelLabelHolder := 'Cancel' asValue.
+    ].
+    ^ cancelLabelHolder.
+!
+
+enableBack
+    "Return a value holder for the input string.
+    "
+    enableBack isNil ifTrue:[
+        enableBack := treeBrowser enableBack.
+    ].
+    ^ enableBack
+!
+
+enableDirectoryUp
+
+    enableDirectoryUp isNil ifTrue:[
+        enableDirectoryUp := treeBrowser enableDirectoryUp.
+    ].
+    ^ enableDirectoryUp
+!
+
+enableForward
+    "Return a value holder for the input string.
+    "
+    enableForward isNil ifTrue:[
+        enableForward := treeBrowser enableForward.
+    ].
+    ^ enableForward
+!
+
+enableHome
+    "Return a value holder for the input string.
+    "
+    enableHome isNil ifTrue:[
+        enableHome := treeBrowser enableHome.
+    ].
+    ^ enableHome
+!
+
+filenameHolder
+    "Return a value holder with the filename.
+     Shown in the filename input-field.
+     Being the selection in the tree.
+    "
+    |holder|
+    holder := builder bindingAt:#filenameHolder.
+
+    holder ifNil:[
+        holder := ValueHolder new.
+        holder addDependent:self.
+        builder aspectAt:#filenameHolder 
+                     put:holder.
+    ].
+
+    ^ holder.
+!
+
+filterHolder
+    "Return a value holder for the input string.
+    "
+
+    filterHolder isNil ifTrue:[
+        filterHolder := treeBrowser filterModel.
+        self pattern notNil ifTrue:[
+            filterHolder value:pattern.
+        ]
+    ].
+    ^ filterHolder
+!
+
+okLabelHolder
+    "automatically generated by UIPainter ..."
+
+    "*** the code below creates a default model when invoked."
+    "*** (which may not be the one you wanted)"
+    "*** Please change as required and accept it in the browser."
+    "*** (and replace this comment by something more useful ;-)"
+
+    okLabelHolder isNil ifTrue:[
+        okLabelHolder := 'OK' asValue.
+    ].
+    ^ okLabelHolder.
+! !
+
+!FileDialog methodsFor:'change & update'!
+
+update:something with:aParameter from:changedObject
+    "Invoked when an object that I depend upon sends a change notification."
+
+    "stub code automatically generated - please change as required"
+
+    changedObject == treeBrowser currentFileNameHolder ifTrue:[
+        | files newDir|
+        files := treeBrowser currentFileNameHolder value.
+
+        (files isEmpty) ifTrue:[
+            self filenameHolder value:nil withoutNotifying:self.
+            treeBrowser hasSelection value:false.
+        ] ifFalse:[
+            treeBrowser hasSelection value:true.
+            files size == 1 ifTrue:[
+                self filenameHolder value:(files first) withoutNotifying:self.    
+            ] ifFalse:[
+                self filenameHolder value:'' withoutNotifying:self.
+            ].
+        ].
+    ].
+    changedObject == self filenameHolder ifTrue:[
+        (changedObject value asFilename exists not) ifTrue:[^ self].
+        treeBrowser currentFileNameHolder value:(OrderedCollection with:(changedObject value asFilename)) withoutNotifying:self.
+    ].
+    changedObject == treeBrowser enableBack ifTrue:[
+        self enableBack value:changedObject value.
+        ^ self.
+    ].
+    changedObject == treeBrowser enableForward ifTrue:[
+        self enableForward value:changedObject value.
+        ^ self.
+    ].
+    changedObject == treeBrowser enableHome ifTrue:[
+        self enableHome value:changedObject value.
+        ^ self.
+    ].
+    changedObject == treeBrowser enableDirectoryUp ifTrue:[
+        self enableDirectoryUp value:changedObject value.
+        ^ self.
+    ].
+    ^ super update:something with:aParameter from:changedObject
+! !
+
+!FileDialog methodsFor:'event handling'!
+
+processEvent:anEvent
+    "filter keyboard events.
+     Return true, if I have eaten the event"
+
+    |focusView key rawKey|
+
+    anEvent isKeyPressEvent ifTrue:[
+        focusView := anEvent targetView.
+        key := anEvent key.
+        rawKey := anEvent rawKey.
+
+        (focusView == filterField) ifTrue:[
+            ^ false.
+        ].
+        (focusView == filenameField) ifTrue:[
+            ^ false.
+        ].
+    ].
+    ^ false
+! !
+
+!FileDialog methodsFor:'initialization & release'!
+
+postBuildFileNameField:aWidget
+
+    filenameField := aWidget.
+!
+
+postBuildFilterField:aWidget
+
+    filterField := aWidget.
+!
+
+postBuildTreeBrowser:aSubCanvasView
+
+    treeBrowser := aSubCanvasView client.
+!
+
+postBuildWith:aBuilder
+    "This is a hook method generated by the Browser.
+     It will be invoked during the initialization of your app/dialog,
+     after all of the visual components have been built, 
+     but BEFORE the top window is made visible.
+     Add any app-specific actions here (reading files, setting up values etc.)
+     See also #postOpenWith:, which is invoked after opening."
+
+    "/ add any code here ...
+
+    ^ super postBuildWith:aBuilder
+!
+
+postOpenWith:aBuilder
+    "This is a hook method generated by the Browser.
+     It will be invoked right after the applications window has been opened.
+     Add any app-specific actions here (starting background processes etc.).
+     See also #postBuildWith:, which is invoked before opening."
+
+    "/ add any code here ...
+    
+
+"/     self windowGroup addPreEventHook:self.
+    treeBrowser currentFileNameHolder addDependent:self.
+    treeBrowser enableBack addDependent:self.
+    treeBrowser enableForward addDependent:self.
+    treeBrowser enableHome addDependent:self.
+    treeBrowser enableDirectoryUp addDependent:self.
+    treeBrowser setNewRoot:((self directory) ? (Filename currentDirectory asAbsoluteFilename)).
+    treeBrowser viewFilesInDirectoryTree value:(viewFiles ? true).
+    treeBrowser currentFileNameHolder value:(OrderedCollection with:(self startFilename)).
+    self filenameHolder value:(self startFilename asString).
+    self window label:(self initialText) ? 'File Dialog'.
+    ^ super postOpenWith:aBuilder
+! !
+
+!FileDialog methodsFor:'user actions'!
+
+doAccept
+    "force accept - ignore in filterField"
+
+    |ev|
+
+    ev := self windowGroup lastEvent.
+    (ev notNil 
+    and:[ev isKeyEvent 
+    and:[ev key == #Return
+    and:[(   ev targetView isSameOrComponentOf:filterField) 
+         or:[ev targetView isSameOrComponentOf:filenameField]]]]) ifTrue:[
+        ^ self
+    ].
+    self result:(self filenameHolder value).
+
+    ^ super doAccept
+!
+
+doBack
+
+    treeBrowser doBack.
+!
+
+doCancel
+
+    self result:nil.
+    ^ super doCancel.
+!
+
+doForward
+
+    treeBrowser doForward.
+!
+
+doGoDirectoryUp
+
+    treeBrowser doGoDirectoryUp.
+!
+
+doGotoHomeDirectory
+
+    treeBrowser doGotoHomeDirectory.
+!
+
+menuDirHistory:backOrForward
+
+    ^ treeBrowser menuDirHistory:backOrForward.
+!
+
+menuDirHistoryBack
+
+    ^ treeBrowser menuDirHistory:#back.
+!
+
+menuDirHistoryForward
+
+    ^ treeBrowser menuDirHistory:#forward.
+! !
+
+!FileDialog class methodsFor:'documentation'!
+
+version
+    ^ '$Header: /cvs/stx/stx/libtool/FileDialog.st,v 1.1 2002-09-25 08:00:23 penk Exp $'
+! !
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FindFileApplication.st	Wed Sep 25 10:00:32 2002 +0200
@@ -0,0 +1,863 @@
+"{ Package: 'stx:libtool' }"
+
+AbstractFileApplicationNoteBookComponent subclass:#FindFileApplication
+	instanceVariableNames:'contentsPatternHolder ignoreCaseInName notSearchForSameContents
+		namePatternHolder ignoreCaseInContents searchDirectoryHolder
+		findFileView searchResultTable resultList enableStop enableSearch
+		stopSignal accessLock searchTask expanded searchRecursively
+		selectionHolder hasListEntries'
+	classVariableNames:''
+	poolDictionaries:''
+	category:'Interface-Tools-File'
+!
+
+
+!FindFileApplication class methodsFor:'instance creation'!
+
+open
+
+    ^ self openOnFileName:(Filename currentDirectory asAbsoluteFilename)
+!
+
+openOnFileName:aFileName
+
+    | instance builder|
+
+    builder := super open.
+    instance := builder application.
+    instance item:(DirectoryContentsBrowser itemClass with:aFileName).
+    ^ builder
+!
+
+openOnFileName:aFileName for:aTargetApplication
+
+    | instance builder|
+
+    builder := super open.
+    instance := builder application.
+    instance item:(DirectoryContentsBrowser itemClass with:aFileName).
+    ^ builder
+! !
+
+!FindFileApplication class methodsFor:'defaults'!
+
+tabStringFor:aApplicationType
+
+    ^ 'Find file in:'
+! !
+
+!FindFileApplication class methodsFor:'interface specs'!
+
+windowSpec
+    "This resource specification was automatically generated
+     by the UIPainter of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the UIPainter may not be able to read the specification."
+
+    "
+     UIPainter new openOnClass:FindFileApplication andSelector:#windowSpec
+     FindFileApplication new openInterface:#windowSpec
+     FindFileApplication open
+    "
+
+    <resource: #canvas>
+
+    ^ 
+     #(#FullSpec
+        #name: #windowSpec
+        #window: 
+       #(#WindowSpec
+          #label: 'File Search'
+          #name: 'File Search'
+          #min: #(#Point 377 131)
+          #max: #(#Point 1280 1024)
+          #bounds: #(#Rectangle 16 42 681 374)
+        )
+        #component: 
+       #(#SpecCollection
+          #collection: #(
+           #(#MenuPanelSpec
+              #name: 'ToolBar1'
+              #layout: #(#LayoutFrame 0 0.0 0 0 0 1.0 32 0)
+              #menu: #searchMenu
+              #textDefault: true
+            )
+           #(#ViewSpec
+              #name: 'Box1'
+              #layout: #(#LayoutFrame 0 0.0 32 0 0 1.0 126 0)
+              #component: 
+             #(#SpecCollection
+                #collection: #(
+                 #(#LabelSpec
+                    #label: 'Search files named:'
+                    #name: 'Label1'
+                    #layout: #(#LayoutFrame 3 0 7 0 148 0 24 0)
+                    #translateLabel: true
+                    #adjust: #left
+                  )
+                 #(#InputFieldSpec
+                    #name: 'EntryField1'
+                    #layout: #(#LayoutFrame 140 0 4 0 -115 1 24 0)
+                    #tabable: true
+                    #model: #namePatternHolder
+                    #immediateAccept: true
+                    #acceptOnLeave: false
+                    #acceptOnPointerLeave: false
+                  )
+                 #(#CheckBoxSpec
+                    #label: 'Ignore case'
+                    #name: 'CheckBox1'
+                    #layout: #(#LayoutFrame -97 1 5 0 1 1 28 0)
+                    #tabable: true
+                    #model: #ignoreCaseInName
+                    #translateLabel: true
+                  )
+                 #(#LabelSpec
+                    #label: 'Containing the string:'
+                    #name: 'Label2'
+                    #layout: #(#LayoutFrame 4 0 31 0 136 0 48 0)
+                    #translateLabel: true
+                    #adjust: #left
+                  )
+                 #(#InputFieldSpec
+                    #name: 'EntryField2'
+                    #layout: #(#LayoutFrame 140 0 29 0 -115 1 49 0)
+                    #enableChannel: #notSearchForSameContents
+                    #tabable: true
+                    #model: #contentsPatternHolder
+                    #immediateAccept: true
+                    #acceptOnPointerLeave: false
+                  )
+                 #(#CheckBoxSpec
+                    #label: 'Ignore case'
+                    #name: 'CheckBox2'
+                    #layout: #(#LayoutFrame -97 1 30 0 4 1 50 0)
+                    #enableChannel: #notSearchForSameContents
+                    #tabable: true
+                    #model: #ignoreCaseInContents
+                    #translateLabel: true
+                  )
+                 #(#LabelSpec
+                    #label: 'Directory:'
+                    #name: 'Directory'
+                    #layout: #(#LayoutFrame 4 0 57 0 136 0 74 0)
+                    #translateLabel: true
+                    #adjust: #left
+                  )
+                 #(#FilenameInputFieldSpec
+                    #name: 'FilenameEntryField1'
+                    #layout: #(#LayoutFrame 140 0 54 0 -115 1 74 0)
+                    #model: #searchDirectoryHolder
+                    #immediateAccept: true
+                    #acceptOnPointerLeave: false
+                  )
+                 #(#CheckBoxSpec
+                    #label: 'Recursively'
+                    #name: 'CheckBox3'
+                    #layout: #(#LayoutFrame -97 1 54 0 1 1 77 0)
+                    #tabable: true
+                    #model: #searchRecursively
+                    #translateLabel: true
+                  )
+                 )
+               
+              )
+            )
+           #(#SequenceViewSpec
+              #name: 'List1'
+              #layout: #(#LayoutFrame 0 0.0 117 0 0 1.0 0 1)
+              #model: #selectionHolder
+              #menu: #menu
+              #hasHorizontalScrollBar: true
+              #hasVerticalScrollBar: true
+              #isMultiSelect: true
+              #doubleClickSelector: #selectInBrowser
+              #useIndex: true
+              #sequenceList: #resultList
+            )
+           )
+         
+        )
+      )
+! !
+
+!FindFileApplication class methodsFor:'menu specs'!
+
+menu
+    "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:FindFileApplication andSelector:#menu
+     (Menu new fromLiteralArrayEncoding:(FindFileApplication menu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #label: 'Select in Browser'
+            #translateLabel: true
+            #isVisible: #isEmbeddedApplication
+            #value: #selectInBrowser
+            #enabled: #hasOneFileSelected
+          )
+         #(#MenuItem
+            #label: 'Copy Selected Files'
+            #translateLabel: true
+            #value: #copySelectedFiles
+            #enabled: #hasSelectionInResultList
+          )
+         #(#MenuItem
+            #label: 'Open in New File Browser'
+            #translateLabel: true
+            #value: #openInNewBrowser
+            #enabled: #hasOneFileSelected
+          )
+         #(#MenuItem
+            #label: 'Remove selected Files'
+            #translateLabel: true
+            #value: #removeFromList
+            #enabled: #hasSelection
+          )
+         #(#MenuItem
+            #label: 'Remove all Files'
+            #translateLabel: true
+            #value: #removeAllFromList
+            #enabled: #hasListEntries
+          )
+         )
+        nil
+        nil
+      )
+!
+
+searchMenu
+    "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:FindFileApplication andSelector:#searchMenu
+     (Menu new fromLiteralArrayEncoding:(FindFileApplication searchMenu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(#Menu
+        #(
+         #(#MenuItem
+            #label: 'Search'
+            #translateLabel: true
+            #isButton: true
+            #value: #doSearch
+            #labelImage: #(#ResourceRetriever #ToolbarIconLibrary #search20x20Icon)
+          )
+         #(#MenuItem
+            #label: 'Stop'
+            #translateLabel: true
+            #isButton: true
+            #value: #stop
+            #enabled: #enableStop
+            #labelImage: #(#ResourceRetriever #ToolbarIconLibrary #stop22x22Icon)
+          )
+         #(#MenuItem
+            #label: 'Clean Up'
+            #translateLabel: true
+            #isButton: true
+            #value: #removeAllFromList
+            #enabled: #hasListEntries
+            #labelImage: #(#ResourceRetriever #Icon #deleteIcon)
+          )
+         #(#MenuItem
+            #label: 'Close'
+            #translateLabel: true
+            #isButton: true
+            #startGroup: #right
+            #value: #doClose
+            #labelImage: #(#ResourceRetriever #AbstractFileBrowser #closeIcon)
+          )
+         )
+        nil
+        nil
+      )
+! !
+
+!FindFileApplication class methodsFor:'tableColumns specs'!
+
+searchResultTable
+    "This resource specification was automatically generated
+     by the DataSetBuilder of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the DataSetBuilder may not be able to read the specification."
+
+    "
+     DataSetBuilder new openOnClass:FindFileApplication andSelector:#searchResultTable
+    "
+
+    <resource: #tableColumns>
+
+    ^#(
+      #(#DataSetColumnSpec
+         #label: 'Filename'
+         #id: 'FileName'
+         #labelButtonType: #Button
+         #model: #fileName
+         #showRowSeparator: false
+         #showColSeparator: false
+       )
+      )
+    
+! !
+
+!FindFileApplication methodsFor:'accessing'!
+
+accessLock
+    "return the value of the instance variable 'accessLock' (automatically generated)"
+
+    accessLock isNil ifTrue:[
+        accessLock := Semaphore forMutualExclusion name:'accessLock'.
+    ].
+    ^ accessLock
+!
+
+stopSignal
+
+    stopSignal isNil ifTrue:[
+        stopSignal := Signal new.
+    ].
+    ^ stopSignal
+! !
+
+!FindFileApplication methodsFor:'actions'!
+
+changeInformationTo:aString
+
+    self changeInformationTo:aString toTab:false
+!
+
+changeInformationTo:aString toTab:aBoolean
+
+    masterApplication isNil ifTrue:[
+        findFileView label:aString
+    ] ifFalse:[
+        aBoolean ifTrue:[
+            masterApplication tabStringChangeTo:aString for:self
+        ]
+    ].
+!
+
+copySelectedFiles
+    |sel list stream|
+
+    sel := self selectionHolder value.
+    list := self resultList.
+    (sel notNil and:[sel notEmpty]) ifTrue:[
+        stream := WriteStream on:''.
+        sel do:[: key |
+            stream nextPutAll:(list at:key).
+            stream cr.
+        ].
+        self window setTextSelection:stream contents.
+        stream close.
+    ].
+!
+
+doSearch
+
+    | namePattern namePatterns contentsPattern dir|
+
+"/    self changeExtentToSeeSearchResult.
+
+    dir := self searchDirectoryHolder value.
+    dir isNil ifTrue:[
+        Dialog warn:'please type in a Directory first'.
+        ^ self.
+    ].
+    dir asFilename exists not ifTrue:[
+        Dialog warn:dir, 'not exists'.
+        ^ self.
+    ].
+    
+    searchTask notNil ifTrue:[
+        (Dialog 
+            confirm:(resources string:'there is already a find file running !!') withCRs
+            yesLabel:(resources at:'Stop and continue')
+            noLabel:(resources at:'Cancel'))
+        ifFalse:[^ self].
+        self stop.
+    ].
+    self enableStop value:true.
+
+    namePattern := self namePatternHolder value.
+    namePattern size == 0 ifTrue:[
+        namePatterns := nil
+    ] ifFalse:[
+        ignoreCaseInName value ifTrue:[
+            namePattern := namePattern asLowercase
+        ].
+        namePatterns := namePattern asCollectionOfSubstringsSeparatedBy:$;
+    ].
+    contentsPattern := self contentsPatternHolder value.
+    contentsPattern size == 0 ifTrue:[
+        contentsPattern := nil
+    ] ifFalse:[
+        self ignoreCaseInContents value ifTrue:[
+            contentsPattern := contentsPattern asLowercase
+        ]
+    ].
+    searchTask := Process for:[
+        [            
+            (self stopSignal) catch:[
+                self resultList removeAll.
+                self changeInformationTo:'Find File ' , '- search started ' toTab:true.
+                self 
+                    doFindFileNamed:namePatterns
+                    ignoreCase:self ignoreCaseInName value
+                    containingString:contentsPattern
+                    ignoreCaseInContents:self ignoreCaseInContents value
+                    sameContentsAsFile:nil 
+                    sameContentsAs:nil 
+                    in:self searchDirectoryHolder value.
+                self enableStop value:false.
+                self enableSearch value:true.
+                self changeInformationTo:'Find File ' , '- search finished' toTab:true.
+            ].
+        ] valueNowOrOnUnwindDo:[
+            searchTask := nil.
+            self enableStop value:false.
+        ]
+    ] priority:(Processor systemBackgroundPriority).
+
+    searchTask name:('FindFile[', self searchDirectoryHolder value asFilename baseName, ']').
+    searchTask resume.
+!
+
+openInNewBrowser
+    |sel|
+
+    sel := self selectionHolder value.
+    (sel notNil and:[sel notEmpty]) ifTrue:[
+        FileBrowserV2 openOn:(self resultList at:sel first) asFilename
+    ].
+!
+
+removeAllFromList
+
+    self resultList removeAll.
+!
+
+removeFromList
+    |sel list|
+
+    sel := self selectionHolder value.
+    list := self resultList.
+    (sel notNil and:[sel notEmpty]) ifTrue:[
+        sel reverseDo:[: key |
+            list removeAtIndex:key
+        ]
+    ].
+!
+
+selectInBrowser
+    |sel entry application|
+
+    sel := self selectionHolder value.
+    (sel notNil and:[sel notEmpty]) ifTrue:[
+        entry := self resultList at:sel first.
+    ].
+    application := self masterApplication.
+    application notNil ifTrue:[ 
+        application gotoFile:(entry asFilename).
+    ].
+!
+
+stop
+
+    searchTask notNil ifTrue:[
+        self accessLock critical:[
+            searchTask interruptWith:[stopSignal raiseRequest].
+        ]
+    ].
+    self enableStop value:false.
+    self enableSearch value:true.
+    self changeInformationTo:'Find File ' , '- search stopped' toTab:true.
+!
+
+stopSearchTask
+    |task|
+
+    (task := searchTask) notNil ifTrue:[
+        searchTask := nil.
+
+        Object errorSignal handle:[:ex|
+            Dialog warn:ex description.
+        ]do:[
+            task isDead ifFalse:[
+                task terminateWithAllSubprocesses.
+                task waitUntilTerminated.
+            ]
+        ]
+    ].
+! !
+
+!FindFileApplication methodsFor:'aspects'!
+
+contentsPatternHolder
+
+    contentsPatternHolder isNil ifTrue:[
+        contentsPatternHolder := nil asValue.
+    ].
+    ^ contentsPatternHolder.
+!
+
+enableSearch
+
+    enableSearch isNil ifTrue:[
+        enableSearch := true asValue.
+    ].
+    ^ enableSearch.
+!
+
+enableStop
+
+    enableStop isNil ifTrue:[
+        enableStop := true asValue.
+    ].
+    ^ enableStop.
+!
+
+hasListEntries
+
+    hasListEntries isNil ifTrue:[
+        hasListEntries := false asValue.
+    ].
+    ^ hasListEntries.
+!
+
+ignoreCaseInContents
+    ignoreCaseInContents isNil ifTrue:[
+        ignoreCaseInContents := false asValue.
+    ].
+    ^ ignoreCaseInContents.
+!
+
+ignoreCaseInName
+
+    ignoreCaseInName isNil ifTrue:[
+        ignoreCaseInName := false asValue.
+    ].
+    ^ ignoreCaseInName.
+!
+
+namePatternHolder
+
+    namePatternHolder isNil ifTrue:[
+        namePatternHolder := '*' asValue.
+    ].
+    ^ namePatternHolder.
+!
+
+notSearchForSameContents
+
+    notSearchForSameContents isNil ifTrue:[
+        notSearchForSameContents := true asValue.
+    ].
+    ^ notSearchForSameContents.
+!
+
+resultList
+
+    resultList isNil ifTrue:[
+        resultList := List new.
+        resultList addDependent:self.
+    ].
+    ^ resultList.
+!
+
+searchDirectoryHolder
+
+    searchDirectoryHolder isNil ifTrue:[
+        searchDirectoryHolder := ValueHolder new.
+    ].
+    ^ searchDirectoryHolder.
+!
+
+searchRecursively
+
+    searchRecursively isNil ifTrue:[
+        searchRecursively := true asValue.
+    ].
+    ^ searchRecursively.
+!
+
+searchResultTable
+
+    searchResultTable isNil ifTrue:[
+        searchResultTable := self class searchResultTable asValue.
+    ].
+    ^ searchResultTable.
+!
+
+selectionHolder
+
+    selectionHolder isNil ifTrue:[
+        selectionHolder := ValueHolder new
+    ].
+    ^ selectionHolder
+! !
+
+!FindFileApplication methodsFor:'change & update'!
+
+update:something with:aParameter from:changedObject
+    "Invoked when an object that I depend upon sends a change notification."
+
+    "stub code automatically generated - please change as required"
+
+    changedObject == self resultList ifTrue:[
+        self hasListEntries value:(self resultList notEmpty).
+        ^ self
+    ].
+    super update:something with:aParameter from:changedObject
+! !
+
+!FindFileApplication methodsFor:'event handling'!
+
+processEvent:anEvent
+    "filter keyboard events.
+     Return true, if I have eaten the event"
+
+    |focusView key rawKey|
+
+    anEvent isKeyPressEvent ifTrue:[
+        focusView := anEvent targetView.
+        key := anEvent key.
+        rawKey := anEvent rawKey.
+
+        (focusView isSameOrComponentOf:self window) ifTrue:[
+            (key == #Return) ifTrue:[
+                (focusView name ~= 'selectionInListView') ifTrue:[
+                    self doSearch.
+                ] ifFalse:[
+                    self hasOneFileSelected ifTrue:[
+                        self isEmbeddedApplication ifTrue:[
+                            self selectInBrowser.
+                        ] ifFalse:[
+                            self openInNewBrowser.
+                        ]
+                    ]
+                ].
+                ^ true
+            ].
+        ]
+    ].
+    ^ false
+! !
+
+!FindFileApplication methodsFor:'private'!
+
+changeExtentToSeeSearchResult
+    
+    | extent window|
+
+    expanded isNil ifTrue:[
+        window := self builder window.
+        window ifNotNil:[
+            window := window topView.
+            extent := window extent.
+            window extent:((extent x) @ (extent y + 300)).
+            expanded := true.
+            window containerChangedSize.
+        ].
+    ].
+! !
+
+!FindFileApplication methodsFor:'private - file stuff'!
+
+doFindFileNamed:namePatterns ignoreCase:ignCaseInName containingString:contentsString ignoreCaseInContents:ignCaseInString sameContentsAsFile:filenameToCompareContentsOrNil sameContentsAs:bytesToCompareContentsOrNil in:aDirectory
+
+    |dir subDirs nameMatches contentsMatches lines contentsToCompare list|
+
+    list := self resultList.
+    bytesToCompareContentsOrNil notNil ifTrue:[
+        contentsToCompare := bytesToCompareContentsOrNil
+    ].
+
+    subDirs := OrderedCollection new.
+
+    dir := aDirectory asFilename.
+    self changeInformationTo:'Find File ' , '- searching .' , ((dir name) copyFrom:(self searchDirectoryHolder value asString size + 1)) toTab:false.
+    (dir directoryContents ? #()) sort do:[:fn |
+        |f|
+
+        f := dir construct:fn.
+        f isDirectory ifTrue:[
+            f isSymbolicLink ifFalse:[
+                subDirs add:f
+            ]
+        ] ifFalse:[
+            (nameMatches := namePatterns isNil) ifFalse:[
+                ignCaseInName ifTrue:[
+                    nameMatches := namePatterns contains:[:aPattern | aPattern match:(fn asLowercase)]
+                ] ifFalse:[
+                    nameMatches := namePatterns contains:[:aPattern | aPattern  match:fn]
+                ]
+            ].
+            nameMatches ifTrue:[
+                filenameToCompareContentsOrNil notNil ifTrue:[
+                    "/ contents compare ...
+                    contentsMatches := false.
+                    f pathName ~= filenameToCompareContentsOrNil pathName ifTrue:[
+                        f fileSize == filenameToCompareContentsOrNil fileSize ifTrue:[
+                            contentsToCompare isNil ifTrue:[
+                                filenameToCompareContentsOrNil fileSize < (512*1024) ifTrue:[
+                                    contentsToCompare := filenameToCompareContentsOrNil binaryContentsOfEntireFile
+                                ]
+                            ].
+                            contentsToCompare isNil ifTrue:[
+                                "/ too large - compare block-wise ...
+                                contentsMatches := (filenameToCompareContentsOrNil sameContentsAs:f).
+                            ] ifFalse:[
+                                contentsMatches := contentsToCompare = (f binaryContentsOfEntireFile).
+                            ]
+                        ].
+                    ] ifFalse:[
+                        f isSymbolicLink ifTrue:[
+                            list add: (f name , ' is a symbolic link to ' , f pathName).
+                        ]
+                    ]
+                ] ifFalse:[
+                    "/ string search ...
+                    (contentsMatches := contentsString isNil) ifFalse:[
+                        (f exists and:[f isReadable]) ifFalse:[
+                            list add: (('*** ' , f pathName , ' skipped - unreadable or bad symbolic link ***') asText colorizeAllWith:(Color red darkened)).
+                        ] ifTrue:[
+                            f fileSize > (4024*1024) ifTrue:[
+                                list add: (('*** ' , f pathName , ' skipped - too large ***') asText colorizeAllWith:(Color red darkened)).
+                            ] ifFalse:[
+                                Stream lineTooLongErrorSignal handle:[:ex |
+                                    |cont|
+
+                                    "/ this typically happens, when a binary file is read linewise ...
+                                    cont := f readStream binary contentsOfEntireFile asString.
+                                    ignCaseInString ifTrue:[
+                                        contentsMatches := cont asLowercase includesString:contentsString asLowercase
+                                    ] ifFalse:[
+                                        contentsMatches := cont includesString:contentsString
+                                    ].
+                                ] do:[    
+                                    lines := f contents ? #().
+                                    ignCaseInString ifTrue:[
+                                        contentsMatches := (lines findFirst:[:l | l asLowercase includesString:contentsString asLowercase]) ~~ 0
+                                    ] ifFalse:[
+                                        contentsMatches := (lines findFirst:[:l | l includesString:contentsString]) ~~ 0
+                                    ].
+                                ].
+                            ].
+                        ].
+                    ].
+                ].
+                contentsMatches ifTrue:[
+                    list add: f asString.
+                ]
+            ]
+        ]
+    ].
+
+    self searchRecursively value ifTrue:[
+        subDirs do:[:dir |
+            self
+                doFindFileNamed:namePatterns 
+                ignoreCase:ignCaseInName 
+                containingString:contentsString 
+                ignoreCaseInContents:ignCaseInString 
+                sameContentsAsFile:filenameToCompareContentsOrNil 
+                sameContentsAs:contentsToCompare
+                in:dir
+        ].
+    ]
+! !
+
+!FindFileApplication methodsFor:'queries'!
+
+getTabStringEnd
+
+" get the tab string from the application list on the class side "
+
+    ^ self fileName directory asString
+!
+
+hasOneFileSelected
+    | sel |
+    sel := self selectionHolder value.
+    ^  (sel notNil and:[sel notEmpty and:[sel size = 1]])
+!
+
+hasSelectionInResultList
+    | sel |
+    sel := self selectionHolder value.
+    ^  (sel notNil and:[sel notEmpty])
+! !
+
+!FindFileApplication methodsFor:'startup & release'!
+
+initialize:aFile
+
+    self searchDirectoryHolder value:(self getDirWithoutFileName:aFile).
+    aFile isDirectory ifTrue:[
+        self namePatternHolder value:'*'.
+    ] ifFalse:[
+        self namePatternHolder value:aFile baseName.
+    ].
+    self enableStop value:false.
+    self enableSearch value:true.
+!
+
+item:aItem
+
+    |file|
+
+    super item:aItem.
+    file := self fileName.
+    self searchDirectoryHolder value:(self getDirWithoutFileName:file).
+    file isDirectory ifTrue:[
+        self namePatternHolder value:'*'.
+    ] ifFalse:[
+        self namePatternHolder value:file baseName.
+    ].
+    self enableStop value:false.
+    self enableSearch value:true.
+    ^ true.
+!
+
+postOpenWith:aBuilder
+
+    self masterApplication isNil ifTrue:[
+        self masterApplication:nil.
+    ].
+    findFileView := aBuilder window.
+    self windowGroup addPreEventHook:self.
+    ^ super postOpenWith:aBuilder.
+!
+
+release
+
+    self stopSearchTask.
+    ^ super release
+! !
+
+!FindFileApplication class methodsFor:'documentation'!
+
+version
+    ^ '$Header: /cvs/stx/stx/libtool/FindFileApplication.st,v 1.1 2002-09-25 08:00:04 penk Exp $'
+! !