FBrowser.st
changeset 1162 08940832d3a8
parent 1160 76bc73e0ab24
child 1166 0029f77ccea7
equal deleted inserted replaced
1161:4130c98f3268 1162:08940832d3a8
   553         ] ifFalse:[
   553         ] ifFalse:[
   554             msg := 'contents has not been saved.\\Modifications will be lost when new file is read.'.
   554             msg := 'contents has not been saved.\\Modifications will be lost when new file is read.'.
   555             label := 'get'.
   555             label := 'get'.
   556         ].
   556         ].
   557         (self ask:(resources at:msg) yesButton:label) ifTrue:[
   557         (self ask:(resources at:msg) yesButton:label) ifTrue:[
       
   558             subView modified:false.
   558             self doFileGet:viaDoubleClick
   559             self doFileGet:viaDoubleClick
   559         ]
   560         ]
   560     ]
   561     ]
   561 
   562 
   562     "Created: 19.6.1996 / 09:38:35 / cg"
   563     "Created: 19.6.1996 / 09:38:35 / cg"
   563     "Modified: 2.4.1997 / 23:24:40 / cg"
   564     "Modified: 23.4.1997 / 13:04:11 / cg"
   564 !
   565 !
   565 
   566 
   566 fileGetInfo
   567 fileGetInfo
   567     "show short file (stat)-info"
   568     "show short file (stat)-info"
   568 
   569 
   585 
   586 
   586     self fileGetInfo:true
   587     self fileGetInfo:true
   587 !
   588 !
   588 
   589 
   589 fileInsert
   590 fileInsert
   590     "insert contents of file at cursor"
   591     "insert contents of file at the cursor position"
   591 
   592 
   592     |fileName|
   593     |fileName|
   593 
   594 
   594     fileName := self getSelectedFileName.
   595     fileName := self getSelectedFileName.
   595     fileName notNil ifTrue:[
   596     fileName notNil ifTrue:[
   596         self showFile:fileName insert:true encoding:fileEncoding
   597         self showFile:fileName insert:true encoding:fileEncoding
   597     ]
   598     ]
   598 
   599 
   599     "Modified: 22.2.1996 / 14:47:16 / cg"
   600     "Modified: 23.4.1997 / 13:06:06 / cg"
   600 !
   601 !
   601 
   602 
   602 fileListMenu
   603 fileListMenu
   603     "return the menu to show in the fileList"
   604     "return the menu to show in the fileList"
   604 
   605 
   734     "Modified: 28.1.1997 / 15:04:42 / stefan"
   735     "Modified: 28.1.1997 / 15:04:42 / stefan"
   735     "Modified: 25.2.1997 / 20:15:06 / cg"
   736     "Modified: 25.2.1997 / 20:15:06 / cg"
   736 !
   737 !
   737 
   738 
   738 filePrint
   739 filePrint
       
   740     "send a files contents to the printer (not in the menu)"
       
   741 
   739     |fileName inStream printStream line|
   742     |fileName inStream printStream line|
   740 
   743 
   741     self withWaitCursorDo:[
   744     self withWaitCursorDo:[
   742         fileName := self getSelectedFileName.
   745         fileName := self getSelectedFileName.
   743         fileName notNil ifTrue:[
   746         fileName notNil ifTrue:[
   758             ]
   761             ]
   759         ].
   762         ].
   760         0 "compiler hint"
   763         0 "compiler hint"
   761     ]
   764     ]
   762 
   765 
   763     "Modified: 9.11.1996 / 00:15:07 / cg"
   766     "Modified: 23.4.1997 / 13:05:40 / cg"
   764 !
   767 !
   765 
   768 
   766 fileRemove
   769 fileRemove
   767     "remove the selected file(s).
   770     "remove the selected file(s).
   768      Query if user really wants to remove the file.
   771      Query if user really wants to remove the file.
   797     ]
   800     ]
   798 !
   801 !
   799 
   802 
   800 fileSelect:lineNr
   803 fileSelect:lineNr
   801     "selected a file - do nothing here"
   804     "selected a file - do nothing here"
       
   805 
   802     ^ self
   806     ^ self
       
   807 
       
   808     "Modified: 23.4.1997 / 13:04:55 / cg"
   803 !
   809 !
   804 
   810 
   805 fileSpawn
   811 fileSpawn
   806     "start another FileBrowser on the selected directory or
   812     "start another FileBrowser on the selected directory or
   807      on the same directory if none is selected."
   813      on the same directory if none is selected."
   827 
   833 
   828     queryBox := FilenameEnterBox 
   834     queryBox := FilenameEnterBox 
   829                     title:(resources at:'create new directory:') withCRs
   835                     title:(resources at:'create new directory:') withCRs
   830                     okText:(resources at:'create')
   836                     okText:(resources at:'create')
   831                     action:[:newName | self doCreateDirectory:newName].
   837                     action:[:newName | self doCreateDirectory:newName].
   832 "/    queryBox initialText:''.
       
   833     queryBox showAtPointer
   838     queryBox showAtPointer
       
   839 
       
   840     "Modified: 23.4.1997 / 13:04:27 / cg"
   834 !
   841 !
   835 
   842 
   836 newFile
   843 newFile
   837     "ask for and create a new file"
   844     "ask for and create a new file"
   838 
   845 
   843                     okText:(resources at:'create')
   850                     okText:(resources at:'create')
   844                     action:[:newName | self doCreateFile:newName].
   851                     action:[:newName | self doCreateFile:newName].
   845     sel := subView selection.
   852     sel := subView selection.
   846     sel notNil ifTrue:[
   853     sel notNil ifTrue:[
   847         queryBox initialText:(sel asString)
   854         queryBox initialText:(sel asString)
   848 "/    ] ifFalse:[
       
   849 "/        queryBox initialText:''
       
   850     ].
   855     ].
   851     queryBox showAtPointer
   856     queryBox showAtPointer
   852 
   857 
   853     "Modified: 21.2.1996 / 01:43:14 / cg"
   858     "Modified: 23.4.1997 / 13:04:38 / cg"
   854 !
   859 !
   855 
   860 
   856 openChangesBrowser
   861 openChangesBrowser
   857     "open a change browser on the selected file(s)"
   862     "open a change browser on the selected file(s)"
   858 
   863 
  1554     ^ self 
  1559     ^ self 
  1555         ask:(resources string:question)
  1560         ask:(resources string:question)
  1556         yesButton:yesButtonText
  1561         yesButton:yesButtonText
  1557 !
  1562 !
  1558 
  1563 
  1559 changeToPreviousDirectory
  1564 getSelectedFileName
  1560     "if text was modified show a queryBox, 
  1565     "returns the currently selected file; shows an error if
  1561      otherwise change immediately to previous directory."
  1566      multiple files are selected"
  1562 
  1567 
  1563     previousDirectory isNil ifTrue:[^ self].
  1568     |sel|
  1564     (self askIfModified:'contents has not been saved.\\Modifications will be lost when directory is changed.'
  1569 
  1565               yesButton:'change') ifTrue:[
  1570     sel := fileListView selection.
  1566         self doChangeCurrentDirectoryTo:previousDirectory updateHistory:false 
  1571     (sel size > 1) ifTrue:[
       
  1572         self onlyOneSelection
       
  1573     ] ifFalse:[
       
  1574         sel notNil ifTrue:[
       
  1575             ^ fileList at:sel first
       
  1576         ]
       
  1577     ].
       
  1578     ^ nil
       
  1579 !
       
  1580 
       
  1581 onlyOneSelection
       
  1582     "show a warning, that only one file must be selected for
       
  1583      this operation"
       
  1584 
       
  1585     self warn:'exactly one file must be selected !!'
       
  1586 !
       
  1587 
       
  1588 selectedFilesDo:aBlock
       
  1589     "evaluate aBlock on all selected files;
       
  1590      show a wait cursor while doing this"
       
  1591 
       
  1592     |sel|
       
  1593 
       
  1594     sel := fileListView selection.
       
  1595     sel notNil ifTrue:[
       
  1596         self withWaitCursorDo:[
       
  1597             sel do:[:aSelectionIndex |
       
  1598                 aBlock value:(fileList at:aSelectionIndex )
       
  1599             ]
       
  1600         ]
  1567     ]
  1601     ]
  1568 !
  1602 
  1569 
  1603 !
  1570 checkIfDirectoryHasChanged
  1604 
  1571     "every checkDelta secs, check if directoy has changed and update the list if so.
  1605 show:something
  1572      Also, we check if the file shown has been touched in the meanwhile (for example,
  1606     "show something in subview and undef acceptAction"
  1573      from another browser) and say 'outdated' in the label if so. 
  1607 
  1574      This avoids confusion if the same file is being edited by two browsers. (or other editors).
  1608     subView contents:something.
  1575      If the text shown in the codeView has been edited, 'modified' is shown.
  1609     subView acceptAction:nil.
  1576     "
  1610     subView modified:false.
  1577 
  1611     currentFileName := nil
  1578     |oldSelection nOld here newState msg newLabel|
  1612 !
  1579 
  1613 
  1580     shown ifTrue:[
  1614 showAlert:aString with:anErrorString
  1581         currentDirectory notNil ifTrue:[
  1615     "show an alertbox, displaying the last Unix-error"
  1582             lockUpdate ifTrue:[
  1616 
  1583                 Processor removeTimedBlock:checkBlock.
  1617     |msg|
  1584                 Processor addTimedBlock:checkBlock afterSeconds:checkDelta.
  1618 
  1585                 ^ self
  1619     anErrorString isNil ifTrue:[
  1586             ].
  1620         msg := aString
  1587 
  1621     ] ifFalse:[
  1588             subView modified ifTrue:[
  1622         msg := aString , '\\(' , anErrorString , ')'
  1589                 newState := ' (modified)'
  1623     ].
  1590             ].
  1624     self warn:msg withCRs
  1591 
  1625 !
  1592             here := currentDirectory pathName.
  1626 
  1593             (OperatingSystem isReadable:here) ifTrue:[
  1627 withoutHiddenFiles:aCollection
  1594                 Processor removeTimedBlock:checkBlock.
  1628     "remove hidden files (i.e. those that start with '.') from
  1595 
  1629      the list in aCollection"
  1596                 (currentDirectory timeOfLastChange > timeOfLastCheck) ifTrue:[
  1630 
  1597                     nOld := fileListView numberOfSelections.
  1631     |newCollection|
  1598                     oldSelection := fileListView selectionValue.
  1632 
  1599                     self updateCurrentDirectory.
  1633     newCollection := aCollection species new.
  1600                     nOld ~~ 0 ifTrue:[
  1634     aCollection do:[:fname |
  1601                         nOld > 1 ifTrue:[
  1635         |ignore|
  1602                             oldSelection do:[:element  |
  1636 
  1603                                 fileListView addElementToSelection:element
  1637         ignore := false.
  1604                             ]
  1638 
  1605                         ] ifFalse:[
  1639         ((fname startsWith:'.') and:[fname ~= '..']) ifTrue:[
  1606                             fileListView selectElementWithoutScroll:oldSelection
  1640             showDotFiles ifFalse:[
  1607                         ]
  1641                 ignore := true
  1608                     ].
       
  1609                 ] ifFalse:[
       
  1610                     Processor addTimedBlock:checkBlock afterSeconds:checkDelta
       
  1611                 ].
       
  1612 
       
  1613                 currentFileName notNil ifTrue:[
       
  1614                     (currentDirectory exists:currentFileName) ifFalse:[
       
  1615                         newState := ' (removed)'.
       
  1616                     ] ifTrue:[
       
  1617                         (currentDirectory timeOfLastChange:currentFileName) > timeOfFileRead ifTrue:[
       
  1618                             newState := ' (outdated)'.
       
  1619                             subView modified ifTrue:[
       
  1620                                 newState := ' (modified & outdated)'
       
  1621                             ]
       
  1622                         ].
       
  1623                     ].
       
  1624                 ].
       
  1625 
       
  1626             ] ifFalse:[         
       
  1627                 "
       
  1628                  if the directory has been deleted, or is not readable ...
       
  1629                 "
       
  1630                 (OperatingSystem isValidPath:here) ifFalse:[
       
  1631                     msg := 'FileBrowser:\\directory %1 is gone ?!!?'
       
  1632                 ] ifTrue:[
       
  1633                     msg := 'FileBrowser:\\directory %1 is no longer readable ?!!?'
       
  1634                 ].
       
  1635                 self warn:(resources string:msg with:here) withCRs.
       
  1636 
       
  1637                 fileListView contents:nil.
       
  1638                 newLabel := myName , ': directory is gone !!'.
       
  1639                 "/ Processor addTimedBlock:checkBlock afterSeconds:checkDelta
       
  1640             ].
       
  1641 
       
  1642             newState notNil ifTrue:[
       
  1643                 newLabel := myName.
       
  1644                 currentFileName notNil ifTrue:[
       
  1645                     newLabel := newLabel , ': ' , currentFileName
       
  1646                 ].
       
  1647                 newLabel := newLabel , newState.
       
  1648             ].
       
  1649             newLabel notNil ifTrue:[
       
  1650                 self label:newLabel.
       
  1651             ]
  1642             ]
  1652         ]
  1643         ].
  1653     ]
  1644         ignore ifFalse:[
  1654 !
  1645             newCollection add:fname
  1655 
  1646         ]
  1656 doChangeCurrentDirectoryTo:fileName updateHistory:updateHistory 
  1647     ].
  1657     "verify argument is name of a readable & executable directory
  1648     ^ newCollection
  1658      and if so, go there"
  1649 
  1659 
  1650     "Modified: 21.2.1996 / 01:33:18 / cg"
  1660     |msg path idx|
  1651 ! !
  1661 
  1652 
  1662     self label:myName; iconLabel:myName.
  1653 !FileBrowser methodsFor:'private - actions & command execution'!
  1663     fileName notNil ifTrue:[
  1654 
  1664         (currentDirectory isDirectory:fileName) ifTrue:[
  1655 binaryFileAction:aFilename
  1665             (currentDirectory isReadable:fileName) ifTrue:[
  1656     "for some binary files, if double clicked, we can do some useful
  1666                 (currentDirectory isExecutable:fileName) ifTrue:[
  1657      action ..."
  1667 
  1658 
  1668                     path := currentDirectory pathName.
  1659     (currentDirectory pathName , '/' , aFilename) asFilename isExecutable ifTrue:[
  1669                     previousDirectory := path.
  1660         (OperatingSystem executeCommand:'cd ',currentDirectory pathName, '; ',aFilename)
  1670 
  1661         ifTrue:[^true].
  1671                     "
  1662     ].
  1672                      remember where we are in the fileList
  1663     ^ self imageAction:aFilename
  1673                      (in case we want to return)
  1664 
  1674                     "
  1665     "Modified: 19.6.1996 / 09:44:07 / cg"
  1675                     idx := DirectoryHistory indexOf:path.
       
  1676                     idx ~~ 0 ifTrue:[
       
  1677                         DirectoryHistoryWhere at:idx put:fileListView firstLineShown
       
  1678                     ].
       
  1679 
       
  1680                     self setCurrentDirectory:fileName.
       
  1681 
       
  1682                     path := currentDirectory pathName.
       
  1683 
       
  1684                     "
       
  1685                      if we have already been there, look for the
       
  1686                      position offset, and scroll the fileList
       
  1687                     "
       
  1688                     idx := DirectoryHistory indexOf:path.
       
  1689                     idx ~~ 0 ifTrue:[
       
  1690                         |pos|
       
  1691 
       
  1692                         pos := DirectoryHistoryWhere at:idx.
       
  1693                         pos notNil ifTrue:[
       
  1694                             fileListView scrollToLine:pos
       
  1695                         ]
       
  1696                     ].
       
  1697 
       
  1698                     updateHistory ifTrue:[
       
  1699                         |pos|
       
  1700 
       
  1701                         (DirectoryHistory includes:path) ifFalse:[
       
  1702                             DirectoryHistory size >= HistorySize ifTrue:[
       
  1703                                 DirectoryHistory removeLast.
       
  1704                                 DirectoryHistoryWhere removeLast
       
  1705                             ]
       
  1706                         ] ifTrue:[
       
  1707                             "already been there before; move the entry to
       
  1708                              the beginning, so it will fall out later."
       
  1709 
       
  1710                             idx := DirectoryHistory indexOf:path.
       
  1711                             DirectoryHistory removeIndex:idx.
       
  1712                             pos := DirectoryHistoryWhere at:idx.
       
  1713                             DirectoryHistoryWhere removeIndex:idx.
       
  1714                         ].
       
  1715                         DirectoryHistory addFirst:path.
       
  1716                         DirectoryHistoryWhere addFirst:pos.
       
  1717                     ].
       
  1718 
       
  1719                     ^ self
       
  1720                 ].
       
  1721                 msg := 'cannot change directory to ''%1'' !!'
       
  1722             ] ifFalse:[
       
  1723                 msg := 'cannot read directory ''%1'' !!'
       
  1724             ]
       
  1725         ] ifFalse:[
       
  1726             msg := '''%1'' is not a directory !!'
       
  1727         ].
       
  1728         self showAlert:(resources string:msg with:fileName) with:nil
       
  1729     ]
       
  1730 !
       
  1731 
       
  1732 doChangeToHomeDirectory
       
  1733     "go to home directory"
       
  1734 
       
  1735     self doChangeCurrentDirectoryTo:(OperatingSystem getHomeDirectory) updateHistory:true
       
  1736 !
       
  1737 
       
  1738 doChangeToParentDirectory
       
  1739     "go to home directory"
       
  1740 
       
  1741     self doChangeCurrentDirectoryTo:'..' updateHistory:true
       
  1742 !
       
  1743 
       
  1744 doCreateDirectory:newName
       
  1745     (currentDirectory includes:newName) ifTrue:[
       
  1746         self warn:'%1 already exists.' with:newName.
       
  1747         ^ self
       
  1748     ].
       
  1749 
       
  1750     (currentDirectory createDirectory:newName) ifTrue:[
       
  1751         self updateCurrentDirectoryIfChanged
       
  1752     ] ifFalse:[
       
  1753         self showAlert:(resources string:'cannot create directory ''%1'' !!' with:newName)
       
  1754                   with:(OperatingSystem lastErrorString)
       
  1755     ]
       
  1756 
       
  1757     "Modified: 19.4.1997 / 15:30:32 / cg"
       
  1758 !
       
  1759 
       
  1760 doCreateFile:newName
       
  1761     |aStream|
       
  1762 
       
  1763     (currentDirectory includes:newName) ifTrue:[
       
  1764         (self
       
  1765             ask:(resources string:'%1 already exists\\truncate ?' with:newName)
       
  1766             yesButton:'truncate'
       
  1767         ) ifFalse:[^ self].
       
  1768     ].
       
  1769 
       
  1770     aStream := FileStream newFileNamed:newName in:currentDirectory.
       
  1771     aStream notNil ifTrue:[
       
  1772         aStream close.
       
  1773         self updateCurrentDirectoryIfChanged
       
  1774     ] ifFalse:[
       
  1775         self showAlert:(resources string:'cannot create file ''%1'' !!' with:newName)
       
  1776                   with:(FileStream lastErrorString)
       
  1777     ]
       
  1778 
       
  1779     "Modified: 19.4.1997 / 15:30:35 / cg"
       
  1780 !
  1666 !
  1781 
  1667 
  1782 doExecuteCommand:command replace:replace
  1668 doExecuteCommand:command replace:replace
  1783     "execute a unix command inserting the output of the command.
  1669     "execute a unix command inserting the output of the command.
  1784      If replace is true, all text is replaced by the commands output;
  1670      If replace is true, all text is replaced by the commands output;
  1952 
  1838 
  1953     "Modified: 21.9.1995 / 11:18:46 / claus"
  1839     "Modified: 21.9.1995 / 11:18:46 / claus"
  1954     "Modified: 19.4.1997 / 15:29:54 / cg"
  1840     "Modified: 19.4.1997 / 15:29:54 / cg"
  1955 !
  1841 !
  1956 
  1842 
       
  1843 imageAction:aFilename
       
  1844     "for some image files, if double clicked, we can do some useful
       
  1845      action ..."
       
  1846 
       
  1847     |img|
       
  1848 
       
  1849     (Image isImageFileSuffix:(aFilename asFilename suffix))
       
  1850     ifTrue:[
       
  1851         img := Image fromFile:(currentDirectory pathName , '/' , aFilename).
       
  1852         img notNil ifTrue:[
       
  1853             img inspect.
       
  1854             ^ true
       
  1855         ]
       
  1856     ].
       
  1857     ^ false
       
  1858 
       
  1859     "Created: 19.6.1996 / 09:43:50 / cg"
       
  1860     "Modified: 18.4.1997 / 14:56:04 / cg"
       
  1861 !
       
  1862 
       
  1863 initialCommandFor:fileName into:aBox
       
  1864     "set a useful initial command for execute box."
       
  1865 
       
  1866     |lcFilename cmd select|
       
  1867 
       
  1868     "/ XXX should be changed to take stuff from a config file
       
  1869     "/ XXX or from resources.
       
  1870 
       
  1871     ((currentDirectory typeOf:fileName) == #regular) ifTrue:[
       
  1872 
       
  1873         (currentDirectory isExecutable:fileName) ifTrue:[
       
  1874             aBox initialText:(fileName , ' <arguments>').
       
  1875             ^ self
       
  1876         ].
       
  1877 
       
  1878         lcFilename := fileName asLowercase.
       
  1879 
       
  1880         select := true.
       
  1881 
       
  1882         "some heuristics - my personal preferences ...
       
  1883          (actually this should come from a configfile)"
       
  1884 
       
  1885         (fileName endsWith:'akefile') ifTrue:[
       
  1886             aBox initialText:'make target' selectFrom:6 to:11.
       
  1887             ^ self
       
  1888         ].
       
  1889         (lcFilename endsWith:'tar.z') ifTrue:[
       
  1890             cmd := 'zcat %1 | tar tvf -'.
       
  1891             select := false.
       
  1892         ].
       
  1893         (fileName endsWith:'.taz') ifTrue:[
       
  1894             aBox initialText:'zcat %1 | tar tvf -'.
       
  1895             select := false.
       
  1896         ].
       
  1897         (fileName endsWith:'.tar') ifTrue:[
       
  1898             cmd := 'tar tvf %1'.
       
  1899             select := 7.
       
  1900         ].
       
  1901         (fileName endsWith:'.zoo') ifTrue:[
       
  1902             cmd := 'zoo -list %1'.
       
  1903             select := 9.
       
  1904         ].
       
  1905         (lcFilename endsWith:'.zip') ifTrue:[
       
  1906             cmd := 'unzip -l %1'.
       
  1907             select := 8.
       
  1908         ].
       
  1909         (lcFilename endsWith:'.z') ifTrue:[
       
  1910             cmd := 'uncompress %1'
       
  1911         ].
       
  1912         (fileName endsWith:'tar.gz') ifTrue:[
       
  1913             cmd := ('gunzip < %1 | tar tvf -' ).
       
  1914             select := false.
       
  1915         ].
       
  1916         (fileName endsWith:'.tgz') ifTrue:[
       
  1917             cmd := ('gunzip < %1 | tar tvf -' ).
       
  1918             select := false.
       
  1919         ].
       
  1920         (fileName endsWith:'.gz') ifTrue:[
       
  1921             cmd := 'gunzip %1'.
       
  1922         ].
       
  1923         (lcFilename endsWith:'.html') ifTrue:[
       
  1924             cmd := 'netscape %1'
       
  1925         ].
       
  1926         (lcFilename endsWith:'.htm') ifTrue:[
       
  1927             cmd := 'netscape %1'
       
  1928         ].
       
  1929         (fileName endsWith:'.uue') ifTrue:[
       
  1930             cmd := 'uudecode %1'
       
  1931         ].
       
  1932         (fileName endsWith:'.c') ifTrue:[
       
  1933             cmd := 'cc -c %1'.
       
  1934             select := 5.
       
  1935         ].
       
  1936         (fileName endsWith:'.cc') ifTrue:[
       
  1937             cmd := 'g++ -c %1'.
       
  1938             select := 6.
       
  1939         ].
       
  1940         (fileName endsWith:'.C') ifTrue:[
       
  1941             cmd := 'g++ -c %1'.
       
  1942             select := 6.
       
  1943         ].
       
  1944         (fileName endsWith:'.xbm') ifTrue:[
       
  1945             cmd := 'bitmap %1'
       
  1946         ].
       
  1947         (lcFilename endsWith:'.ps') ifTrue:[
       
  1948             cmd := 'ghostview %1'
       
  1949         ].
       
  1950         ((fileName endsWith:'.1') 
       
  1951         or:[fileName endsWith:'.man']) ifTrue:[
       
  1952             cmd := 'nroff -man %1'.
       
  1953             select := 10.
       
  1954         ].
       
  1955 
       
  1956         cmd isNil ifTrue:[
       
  1957             DefaultCommandPerSuffix isNil ifTrue:[
       
  1958                 cmd := '<cmd>'
       
  1959             ] ifFalse:[
       
  1960                 cmd := DefaultCommandPerSuffix 
       
  1961                         at:(lcFilename asFilename suffix)
       
  1962                         ifAbsent:'<cmd>'.
       
  1963             ].
       
  1964             cmd := cmd , ' %1'.
       
  1965         ].
       
  1966 
       
  1967         cmd := cmd bindWith:fileName.
       
  1968         select == false ifTrue:[
       
  1969             aBox initialText:cmd
       
  1970         ] ifFalse:[
       
  1971             select isInteger ifFalse:[
       
  1972                 select := (cmd indexOf:Character space ifAbsent:[cmd size + 1]) - 1.
       
  1973             ].
       
  1974             aBox initialText:cmd selectFrom:1 to:select
       
  1975         ]
       
  1976     ]
       
  1977 
       
  1978     "Modified: 4.4.1997 / 12:26:40 / cg"
       
  1979 !
       
  1980 
       
  1981 nonBinaryFileAction:aFilename
       
  1982     "for some nonBinary files, if double clicked, we can do some useful
       
  1983      action ..."
       
  1984 
       
  1985     |fullPath lcName|
       
  1986 
       
  1987     fullPath := currentDirectory pathName , '/' , aFilename.
       
  1988     lcName := aFilename asLowercase.
       
  1989     ((lcName endsWith:'.htm') or:[lcName endsWith:'.html']) ifTrue:[
       
  1990         HTMLDocumentView openOn:fullPath.
       
  1991         ^ true
       
  1992     ].
       
  1993 
       
  1994     OperatingSystem isUNIXlike ifTrue:[
       
  1995         (#('.man' '.1' '.2' '.3') findFirst:[:suff | aFilename endsWith:suff]) ~~ 0 
       
  1996         ifTrue:[
       
  1997              HTMLDocumentView openFullOnText:(HTMLDocGenerator manPageForFile:fullPath).
       
  1998             ^ true
       
  1999         ]
       
  2000     ].
       
  2001     ^ self imageAction:aFilename
       
  2002 
       
  2003     "Created: 19.6.1996 / 09:36:38 / cg"
       
  2004     "Modified: 4.4.1997 / 10:49:00 / cg"
       
  2005 ! !
       
  2006 
       
  2007 !FileBrowser methodsFor:'private - directory stuff'!
       
  2008 
       
  2009 changeToPreviousDirectory
       
  2010     "if text was modified show a queryBox, 
       
  2011      otherwise change immediately to previous directory."
       
  2012 
       
  2013     previousDirectory isNil ifTrue:[^ self].
       
  2014     (self askIfModified:'contents has not been saved.\\Modifications will be lost when directory is changed.'
       
  2015               yesButton:'change') ifTrue:[
       
  2016         self doChangeCurrentDirectoryTo:previousDirectory updateHistory:false 
       
  2017     ]
       
  2018 !
       
  2019 
       
  2020 checkIfDirectoryHasChanged
       
  2021     "every checkDelta secs, check if directoy has changed and update the list if so.
       
  2022      Also, we check if the file shown has been touched in the meanwhile (for example,
       
  2023      from another browser) and say 'outdated' in the label if so. 
       
  2024      This avoids confusion if the same file is being edited by two browsers. (or other editors).
       
  2025      If the text shown in the codeView has been edited, 'modified' is shown.
       
  2026     "
       
  2027 
       
  2028     |oldSelection nOld here newState msg newLabel|
       
  2029 
       
  2030     shown ifTrue:[
       
  2031         currentDirectory notNil ifTrue:[
       
  2032             lockUpdate ifTrue:[
       
  2033                 Processor removeTimedBlock:checkBlock.
       
  2034                 Processor addTimedBlock:checkBlock afterSeconds:checkDelta.
       
  2035                 ^ self
       
  2036             ].
       
  2037 
       
  2038             subView modified ifTrue:[
       
  2039                 newState := ' (modified)'
       
  2040             ].
       
  2041 
       
  2042             here := currentDirectory pathName.
       
  2043             (OperatingSystem isReadable:here) ifTrue:[
       
  2044                 Processor removeTimedBlock:checkBlock.
       
  2045 
       
  2046                 (currentDirectory timeOfLastChange > timeOfLastCheck) ifTrue:[
       
  2047                     nOld := fileListView numberOfSelections.
       
  2048                     oldSelection := fileListView selectionValue.
       
  2049                     self updateCurrentDirectory.
       
  2050                     nOld ~~ 0 ifTrue:[
       
  2051                         nOld > 1 ifTrue:[
       
  2052                             oldSelection do:[:element  |
       
  2053                                 fileListView addElementToSelection:element
       
  2054                             ]
       
  2055                         ] ifFalse:[
       
  2056                             fileListView selectElementWithoutScroll:oldSelection
       
  2057                         ]
       
  2058                     ].
       
  2059                 ] ifFalse:[
       
  2060                     Processor addTimedBlock:checkBlock afterSeconds:checkDelta
       
  2061                 ].
       
  2062 
       
  2063                 currentFileName notNil ifTrue:[
       
  2064                     (currentDirectory exists:currentFileName) ifFalse:[
       
  2065                         newState := ' (removed)'.
       
  2066                     ] ifTrue:[
       
  2067                         (currentDirectory timeOfLastChange:currentFileName) > timeOfFileRead ifTrue:[
       
  2068                             newState := ' (outdated)'.
       
  2069                             subView modified ifTrue:[
       
  2070                                 newState := ' (modified & outdated)'
       
  2071                             ]
       
  2072                         ].
       
  2073                     ].
       
  2074                 ].
       
  2075 
       
  2076             ] ifFalse:[         
       
  2077                 "
       
  2078                  if the directory has been deleted, or is not readable ...
       
  2079                 "
       
  2080                 (OperatingSystem isValidPath:here) ifFalse:[
       
  2081                     msg := 'FileBrowser:\\directory %1 is gone ?!!?'
       
  2082                 ] ifTrue:[
       
  2083                     msg := 'FileBrowser:\\directory %1 is no longer readable ?!!?'
       
  2084                 ].
       
  2085                 self warn:(resources string:msg with:here) withCRs.
       
  2086 
       
  2087                 fileListView contents:nil.
       
  2088                 newLabel := myName , ': directory is gone !!'.
       
  2089                 "/ Processor addTimedBlock:checkBlock afterSeconds:checkDelta
       
  2090             ].
       
  2091 
       
  2092             newState notNil ifTrue:[
       
  2093                 newLabel := myName.
       
  2094                 currentFileName notNil ifTrue:[
       
  2095                     newLabel := newLabel , ': ' , currentFileName
       
  2096                 ].
       
  2097                 newLabel := newLabel , newState.
       
  2098             ].
       
  2099             newLabel notNil ifTrue:[
       
  2100                 self label:newLabel.
       
  2101             ]
       
  2102         ]
       
  2103     ]
       
  2104 !
       
  2105 
       
  2106 doChangeCurrentDirectoryTo:fileName updateHistory:updateHistory 
       
  2107     "verify argument is name of a readable & executable directory
       
  2108      and if so, go there"
       
  2109 
       
  2110     |msg path idx|
       
  2111 
       
  2112     self label:myName; iconLabel:myName.
       
  2113     fileName notNil ifTrue:[
       
  2114         (currentDirectory isDirectory:fileName) ifTrue:[
       
  2115             (currentDirectory isReadable:fileName) ifTrue:[
       
  2116                 (currentDirectory isExecutable:fileName) ifTrue:[
       
  2117 
       
  2118                     path := currentDirectory pathName.
       
  2119                     previousDirectory := path.
       
  2120 
       
  2121                     "
       
  2122                      remember where we are in the fileList
       
  2123                      (in case we want to return)
       
  2124                     "
       
  2125                     idx := DirectoryHistory indexOf:path.
       
  2126                     idx ~~ 0 ifTrue:[
       
  2127                         DirectoryHistoryWhere at:idx put:fileListView firstLineShown
       
  2128                     ].
       
  2129 
       
  2130                     self setCurrentDirectory:fileName.
       
  2131 
       
  2132                     path := currentDirectory pathName.
       
  2133 
       
  2134                     "
       
  2135                      if we have already been there, look for the
       
  2136                      position offset, and scroll the fileList
       
  2137                     "
       
  2138                     idx := DirectoryHistory indexOf:path.
       
  2139                     idx ~~ 0 ifTrue:[
       
  2140                         |pos|
       
  2141 
       
  2142                         pos := DirectoryHistoryWhere at:idx.
       
  2143                         pos notNil ifTrue:[
       
  2144                             fileListView scrollToLine:pos
       
  2145                         ]
       
  2146                     ].
       
  2147 
       
  2148                     updateHistory ifTrue:[
       
  2149                         |pos|
       
  2150 
       
  2151                         (DirectoryHistory includes:path) ifFalse:[
       
  2152                             DirectoryHistory size >= HistorySize ifTrue:[
       
  2153                                 DirectoryHistory removeLast.
       
  2154                                 DirectoryHistoryWhere removeLast
       
  2155                             ]
       
  2156                         ] ifTrue:[
       
  2157                             "already been there before; move the entry to
       
  2158                              the beginning, so it will fall out later."
       
  2159 
       
  2160                             idx := DirectoryHistory indexOf:path.
       
  2161                             DirectoryHistory removeIndex:idx.
       
  2162                             pos := DirectoryHistoryWhere at:idx.
       
  2163                             DirectoryHistoryWhere removeIndex:idx.
       
  2164                         ].
       
  2165                         DirectoryHistory addFirst:path.
       
  2166                         DirectoryHistoryWhere addFirst:pos.
       
  2167                     ].
       
  2168 
       
  2169                     ^ self
       
  2170                 ].
       
  2171                 msg := 'cannot change directory to ''%1'' !!'
       
  2172             ] ifFalse:[
       
  2173                 msg := 'cannot read directory ''%1'' !!'
       
  2174             ]
       
  2175         ] ifFalse:[
       
  2176             msg := '''%1'' is not a directory !!'
       
  2177         ].
       
  2178         self showAlert:(resources string:msg with:fileName) with:nil
       
  2179     ]
       
  2180 !
       
  2181 
       
  2182 doChangeToHomeDirectory
       
  2183     "go to home directory"
       
  2184 
       
  2185     self doChangeCurrentDirectoryTo:(OperatingSystem getHomeDirectory) updateHistory:true
       
  2186 !
       
  2187 
       
  2188 doChangeToParentDirectory
       
  2189     "go to home directory"
       
  2190 
       
  2191     self doChangeCurrentDirectoryTo:'..' updateHistory:true
       
  2192 !
       
  2193 
       
  2194 doCreateDirectory:newName
       
  2195     (currentDirectory includes:newName) ifTrue:[
       
  2196         self warn:'%1 already exists.' with:newName.
       
  2197         ^ self
       
  2198     ].
       
  2199 
       
  2200     (currentDirectory createDirectory:newName) ifTrue:[
       
  2201         self updateCurrentDirectoryIfChanged
       
  2202     ] ifFalse:[
       
  2203         self showAlert:(resources string:'cannot create directory ''%1'' !!' with:newName)
       
  2204                   with:(OperatingSystem lastErrorString)
       
  2205     ]
       
  2206 
       
  2207     "Modified: 19.4.1997 / 15:30:32 / cg"
       
  2208 !
       
  2209 
       
  2210 setCurrentDirectory:aPathName
       
  2211     "setup for another directory"
       
  2212 
       
  2213     |newDirectory|
       
  2214 
       
  2215     aPathName isEmpty ifTrue:[^ self].
       
  2216     (currentDirectory isDirectory:aPathName) ifTrue:[
       
  2217         newDirectory := FileDirectory directoryNamed:aPathName in:currentDirectory.
       
  2218         newDirectory notNil ifTrue:[
       
  2219             self currentDirectory:newDirectory pathName.
       
  2220             currentFileName notNil ifTrue:[
       
  2221                 fileListView contents:nil.
       
  2222                 currentFileName := nil.
       
  2223             ] ifFalse:[
       
  2224                 fileListView setSelection:nil.
       
  2225                 fileListView scrollToTop.
       
  2226             ].
       
  2227             self updateCurrentDirectory.
       
  2228             self showInfo.
       
  2229         ]
       
  2230     ]
       
  2231 
       
  2232     "Modified: 21.9.1995 / 11:22:45 / claus"
       
  2233     "Modified: 25.5.1996 / 12:27:01 / cg"
       
  2234 !
       
  2235 
       
  2236 updateCurrentDirectoryIfChanged
       
  2237     (currentDirectory timeOfLastChange > timeOfLastCheck) ifTrue:[
       
  2238         self updateCurrentDirectory
       
  2239     ]
       
  2240 
       
  2241     "Modified: 19.4.1997 / 15:30:03 / cg"
       
  2242 ! !
       
  2243 
       
  2244 !FileBrowser methodsFor:'private - encoding'!
       
  2245 
       
  2246 guessEncodingFrom:aBuffer
       
  2247     "look for a string
       
  2248         encoding #name
       
  2249      or:
       
  2250         encoding: name
       
  2251      within the given buffer (which is usually the first few
       
  2252      bytes of a textFile"
       
  2253 
       
  2254     |n "{Class: SmallInteger }"
       
  2255      binary idx s w w2|
       
  2256 
       
  2257     binary := false.
       
  2258     n := aBuffer size.
       
  2259 
       
  2260     (idx := aBuffer findString:'encoding') ~~ 0 ifTrue:[
       
  2261         s := ReadStream on:aBuffer.
       
  2262         s position:idx + 8.
       
  2263         s skipSeparators.
       
  2264         s peek == $: ifTrue:[
       
  2265             s next.
       
  2266             s skipSeparators. 
       
  2267         ] ifFalse:[
       
  2268             s peek == $# ifTrue:[s next].
       
  2269         ].
       
  2270         w := s upToSeparator.
       
  2271         w notNil ifTrue:[
       
  2272             ^ w asSymbol
       
  2273         ].
       
  2274     ].
       
  2275 
       
  2276     1 to:n do:[:i |
       
  2277         (aBuffer at:i) isPrintable ifFalse:[binary := true].
       
  2278     ].
       
  2279 
       
  2280     binary ifTrue:[
       
  2281         "/ look for JIS7 / EUC encoding
       
  2282 
       
  2283         (aBuffer findString:(JISEncodedString jis7KanjiEscapeSequence)) ~~ 0 ifTrue:[
       
  2284             ^ #jis7
       
  2285         ].
       
  2286         (aBuffer findString:(JISEncodedString oldJis7KanjiEscapeSequence)) ~~ 0 ifTrue:[
       
  2287             ^ #jis7
       
  2288         ].
       
  2289         ^ #binary
       
  2290     ].
       
  2291     ^ #ascii
       
  2292 
       
  2293     "Created: 26.2.1996 / 17:43:08 / cg"
       
  2294     "Modified: 23.1.1997 / 20:39:25 / cg"
       
  2295 !
       
  2296 
       
  2297 validateFontEncodingFor:newEncoding ask:ask
       
  2298     "if required, query user if he/she wants to change to another font,
       
  2299      which is able to display text encoded as specified by newEncoding"
       
  2300 
       
  2301     |fontsEncoding msg filter f defaultFont|
       
  2302 
       
  2303     fontsEncoding := subView font encoding.
       
  2304 
       
  2305     ((newEncoding == #jis7) or:[newEncoding == #euc]) ifTrue:[
       
  2306         (fontsEncoding notNil and:[fontsEncoding startsWith:'jis']) ifFalse:[
       
  2307             msg := 'switch to a JIS encoded font ?'.
       
  2308             filter := [:f | |coding|
       
  2309                             (coding := f encoding) notNil 
       
  2310                             and:['jis*' match:coding]].
       
  2311         ]
       
  2312     ].
       
  2313     (newEncoding == #gb) ifTrue:[
       
  2314         (fontsEncoding notNil and:[fontsEncoding startsWith:'gb']) ifFalse:[
       
  2315             msg := 'switch to a GB encoded font ?'.
       
  2316             filter := [:f | |coding|
       
  2317                             (coding := f encoding) notNil 
       
  2318                             and:['gb*' match:coding]].
       
  2319         ]
       
  2320     ].
       
  2321     (newEncoding == #big5) ifTrue:[
       
  2322         (fontsEncoding notNil and:[fontsEncoding startsWith:'big5']) ifFalse:[
       
  2323             msg := 'switch to a BIG-5 encoded font ?'.
       
  2324             filter := [:f | |coding|
       
  2325                             (coding := f encoding) notNil 
       
  2326                             and:['big5*' match:coding]].
       
  2327         ]
       
  2328     ].
       
  2329     (newEncoding == #ksc) ifTrue:[
       
  2330         (fontsEncoding notNil and:[fontsEncoding startsWith:'ksc']) ifFalse:[
       
  2331             msg := 'switch to a KSC encoded font ?'.
       
  2332             filter := [:f | |coding|
       
  2333                             (coding := f encoding) notNil 
       
  2334                             and:['ksc*' match:coding]].
       
  2335         ]
       
  2336     ] ifFalse:[
       
  2337         fontsEncoding notNil ifTrue:[
       
  2338             ((fontsEncoding startsWith:'jis')
       
  2339             or:[(fontsEncoding startsWith:'gb')
       
  2340             or:[(fontsEncoding startsWith:'ksc')
       
  2341             or:[(fontsEncoding startsWith:'big5')]]])
       
  2342             ifTrue:[
       
  2343                 msg := 'switch back to an ASCII encoded font ?'.
       
  2344                 filter := [:f | |coding|
       
  2345                                 (coding := f encoding) notNil 
       
  2346                                 and:[('ascii' match:coding)
       
  2347                                      or:['iso*' match:coding]]].
       
  2348                 defaultFont := TextView defaultFont
       
  2349             ] ifFalse:[
       
  2350                 (fontsEncoding notNil and:[fontsEncoding startsWith:'iso8859']) ifTrue:[
       
  2351                     msg := 'switch to a ''' , newEncoding , ''' encoded font ?'.
       
  2352                     filter := [:f | |coding|
       
  2353                                     (coding := f encoding) notNil 
       
  2354                                     and:[newEncoding asLowercase = coding asLowercase]].
       
  2355                 ].
       
  2356             ].
       
  2357         ]
       
  2358     ].
       
  2359 
       
  2360     msg isNil ifTrue:[
       
  2361         "/ mhmh - can be represented in current font
       
  2362     ].
       
  2363 
       
  2364     msg notNil ifTrue:[
       
  2365         defaultFont isNil ifTrue:[
       
  2366             defaultFont := device 
       
  2367                                 listOfAvailableFonts 
       
  2368                                     detect:[:f | filter value:f]
       
  2369                                     ifNone:nil.
       
  2370             defaultFont isNil ifTrue:[
       
  2371                 self warn:'your display does not seem to provide any ' , newEncoding , '-encoded font.'.
       
  2372                 ^ self.
       
  2373             ]
       
  2374         ].
       
  2375 
       
  2376         (ask not or:[self confirm:(resources string:msg) withCRs])
       
  2377         ifTrue:[
       
  2378             f := FontPanel 
       
  2379                 fontFromUserInitial:defaultFont
       
  2380                               title:(resources string:'font selection')
       
  2381                              filter:filter.
       
  2382             f notNil ifTrue:[
       
  2383                 subView font:f
       
  2384             ]
       
  2385         ]
       
  2386     ]
       
  2387 
       
  2388     "Created: 26.10.1996 / 12:06:54 / cg"
       
  2389 ! !
       
  2390 
       
  2391 !FileBrowser methodsFor:'private - file stuff'!
       
  2392 
       
  2393 doCreateFile:newName
       
  2394     "create an empty file"
       
  2395 
       
  2396     |aStream|
       
  2397 
       
  2398     (currentDirectory includes:newName) ifTrue:[
       
  2399         (self
       
  2400             ask:(resources string:'%1 already exists\\truncate ?' with:newName)
       
  2401             yesButton:'truncate'
       
  2402         ) ifFalse:[^ self].
       
  2403     ].
       
  2404 
       
  2405     aStream := FileStream newFileNamed:newName in:currentDirectory.
       
  2406     aStream notNil ifTrue:[
       
  2407         aStream close.
       
  2408         self updateCurrentDirectoryIfChanged
       
  2409     ] ifFalse:[
       
  2410         self showAlert:(resources string:'cannot create file ''%1'' !!' with:newName)
       
  2411                   with:(FileStream lastErrorString)
       
  2412     ]
       
  2413 
       
  2414     "Modified: 23.4.1997 / 13:19:12 / cg"
       
  2415 !
       
  2416 
  1957 doFileGet:viaDoubleClick
  2417 doFileGet:viaDoubleClick
  1958     "get selected file - show contents in subView"
  2418     "get selected file - show contents in subView.
       
  2419      This is invoked either by the 'get file' menu item, or via double click.
       
  2420      When invoked via the menu (viaDoubleClick argument is false),
       
  2421      the automatic file action is not performed - instead, the file is always
       
  2422      shown in the codeView (if possible).
       
  2423      This distinction was done to allow xpm or xbm files (which ahve an automatic
       
  2424      action) to be edited."
  1959 
  2425 
  1960     |fileName iconLbl winLbl|
  2426     |fileName iconLbl winLbl|
  1961 
  2427 
  1962     self withReadCursorDo:[
  2428     self withReadCursorDo:[
  1963         fileName := self getSelectedFileName.
  2429         fileName := self getSelectedFileName.
  1995             self iconLabel:iconLbl.
  2461             self iconLabel:iconLbl.
  1996         ]
  2462         ]
  1997     ]
  2463     ]
  1998 
  2464 
  1999     "Created: 19.6.1996 / 09:39:07 / cg"
  2465     "Created: 19.6.1996 / 09:39:07 / cg"
  2000     "Modified: 7.1.1997 / 20:21:44 / cg"
  2466     "Modified: 23.4.1997 / 13:19:01 / cg"
  2001 !
  2467 !
  2002 
  2468 
  2003 doRemove
  2469 doRemove
  2004     "remove the selected file(s) - no questions asked"
  2470     "remove the selected file(s) - no questions asked"
  2005 
  2471 
  2074 
  2540 
  2075     "Modified: 19.4.1997 / 14:03:55 / cg"
  2541     "Modified: 19.4.1997 / 14:03:55 / cg"
  2076 !
  2542 !
  2077 
  2543 
  2078 doRename:oldName to:newName
  2544 doRename:oldName to:newName
       
  2545     "rename file(s) (or directories)"
       
  2546 
  2079     (oldName notNil and:[newName notNil]) ifTrue:[
  2547     (oldName notNil and:[newName notNil]) ifTrue:[
  2080         (oldName isBlank or:[newName isBlank]) ifFalse:[
  2548         (oldName isBlank or:[newName isBlank]) ifFalse:[
  2081             currentDirectory renameFile:oldName newName:newName.
  2549             currentDirectory renameFile:oldName newName:newName.
  2082             self updateCurrentDirectoryIfChanged.
  2550             self updateCurrentDirectoryIfChanged.
  2083         ]
  2551         ]
  2084     ]
  2552     ]
  2085 
  2553 
  2086     "Modified: 19.4.1997 / 15:30:49 / cg"
  2554     "Modified: 23.4.1997 / 13:19:37 / cg"
  2087 !
  2555 ! !
       
  2556 
       
  2557 !FileBrowser methodsFor:'private - file type & info'!
  2088 
  2558 
  2089 fileCommentStrings
  2559 fileCommentStrings
  2090     "return useful comment definition; based upon the fileName for now"
  2560     "return a useful comment definition; based upon the fileName for now"
  2091 
  2561 
  2092     "/ for now,
  2562     "/ for now,
  2093     "/ define comment strings, by heuristics;
  2563     "/ define comment strings, by heuristics;
  2094     "/ (should look for some mode= or similar string
  2564     "/ (should look for some mode= or similar string
  2095     "/  found in the file itself - like emacs does it)
  2565     "/  found in the file itself - like emacs does it)
  2114     "/ smalltalk comments
  2584     "/ smalltalk comments
  2115 
  2585 
  2116     ^ #('"/' ('"' '"')).
  2586     ^ #('"/' ('"' '"')).
  2117 
  2587 
  2118     "Created: 7.1.1997 / 20:30:00 / cg"
  2588     "Created: 7.1.1997 / 20:30:00 / cg"
       
  2589     "Modified: 23.4.1997 / 13:11:49 / cg"
  2119 !
  2590 !
  2120 
  2591 
  2121 fileTypeSpecificActions
  2592 fileTypeSpecificActions
  2122     "any special fileTypeSpecific actions are done here,
  2593     "any special fileTypeSpecific actions are done here,
  2123      when a new file is selected"
  2594      when a new file is selected"
  2206 getInfoFile
  2677 getInfoFile
  2207     "get filename of a description-file (.dir.info, README etc.);
  2678     "get filename of a description-file (.dir.info, README etc.);
  2208      This file is automatically shown when a directory is enterred.
  2679      This file is automatically shown when a directory is enterred.
  2209      You can add more names below if you like."
  2680      You can add more names below if you like."
  2210 
  2681 
  2211     #( '.dir.info'
  2682     #( 
       
  2683        '.dir.info'
  2212        'README'
  2684        'README'
  2213        'ReadMe'
  2685        'ReadMe'
  2214        'Readme'
  2686        'Readme'
  2215        'readme' 
  2687        'readme'
       
  2688        'read.me'
       
  2689        'Read.me'
       
  2690        'READ.ME'
  2216     ) do:[:f |
  2691     ) do:[:f |
  2217         (currentDirectory isReadable:f) ifTrue:[
  2692         (currentDirectory isReadable:f) ifTrue:[
  2218             (currentDirectory isDirectory:f) ifFalse:[^ f].
  2693             (currentDirectory isDirectory:f) ifFalse:[^ f].
  2219         ]
  2694         ]
  2220     ].
  2695     ].
  2221     ^ nil
  2696     ^ nil
       
  2697 
       
  2698     "Modified: 23.4.1997 / 13:12:36 / cg"
  2222 !
  2699 !
  2223 
  2700 
  2224 getModeString:modeBits
  2701 getModeString:modeBits
  2225     "convert file-mode bits into a more user-friendly string.
  2702     "convert file-mode bits into a more user-friendly string.
  2226      This is wrong here - should be moved into OperatingSystem."
  2703      This is wrong here - should be moved into OperatingSystem."
  2254             ].
  2731             ].
  2255             modeString := modeString copyWith:ch 
  2732             modeString := modeString copyWith:ch 
  2256         ]
  2733         ]
  2257     ].
  2734     ].
  2258     ^ modeString
  2735     ^ modeString
  2259 !
       
  2260 
       
  2261 getSelectedFileName
       
  2262     "returns the currently selected file; shows an error if
       
  2263      multiple files are selected"
       
  2264 
       
  2265     |sel|
       
  2266 
       
  2267     sel := fileListView selection.
       
  2268     (sel size > 1) ifTrue:[
       
  2269         self onlyOneSelection
       
  2270     ] ifFalse:[
       
  2271         sel notNil ifTrue:[
       
  2272             ^ fileList at:sel first
       
  2273         ]
       
  2274     ].
       
  2275     ^ nil
       
  2276 !
       
  2277 
       
  2278 guessEncodingFrom:aBuffer
       
  2279     "look for a string
       
  2280         encoding #name
       
  2281      or:
       
  2282         encoding: name
       
  2283      within the given buffer (which is usually the first few
       
  2284      bytes of a textFile"
       
  2285 
       
  2286     |n "{Class: SmallInteger }"
       
  2287      binary idx s w w2|
       
  2288 
       
  2289     binary := false.
       
  2290     n := aBuffer size.
       
  2291 
       
  2292     (idx := aBuffer findString:'encoding') ~~ 0 ifTrue:[
       
  2293         s := ReadStream on:aBuffer.
       
  2294         s position:idx + 8.
       
  2295         s skipSeparators.
       
  2296         s peek == $: ifTrue:[
       
  2297             s next.
       
  2298             s skipSeparators. 
       
  2299         ] ifFalse:[
       
  2300             s peek == $# ifTrue:[s next].
       
  2301         ].
       
  2302         w := s upToSeparator.
       
  2303         w notNil ifTrue:[
       
  2304             ^ w asSymbol
       
  2305         ].
       
  2306     ].
       
  2307 
       
  2308     1 to:n do:[:i |
       
  2309         (aBuffer at:i) isPrintable ifFalse:[binary := true].
       
  2310     ].
       
  2311 
       
  2312     binary ifTrue:[
       
  2313         "/ look for JIS7 / EUC encoding
       
  2314 
       
  2315         (aBuffer findString:(JISEncodedString jis7KanjiEscapeSequence)) ~~ 0 ifTrue:[
       
  2316             ^ #jis7
       
  2317         ].
       
  2318         (aBuffer findString:(JISEncodedString oldJis7KanjiEscapeSequence)) ~~ 0 ifTrue:[
       
  2319             ^ #jis7
       
  2320         ].
       
  2321         ^ #binary
       
  2322     ].
       
  2323     ^ #ascii
       
  2324 
       
  2325     "Created: 26.2.1996 / 17:43:08 / cg"
       
  2326     "Modified: 23.1.1997 / 20:39:25 / cg"
       
  2327 !
       
  2328 
       
  2329 initialCommandFor:fileName into:aBox
       
  2330     "set a useful initial command for execute box."
       
  2331 
       
  2332     |lcFilename cmd select|
       
  2333 
       
  2334     "/ XXX should be changed to take stuff from a config file
       
  2335     "/ XXX or from resources.
       
  2336 
       
  2337     ((currentDirectory typeOf:fileName) == #regular) ifTrue:[
       
  2338 
       
  2339         (currentDirectory isExecutable:fileName) ifTrue:[
       
  2340             aBox initialText:(fileName , ' <arguments>').
       
  2341             ^ self
       
  2342         ].
       
  2343 
       
  2344         lcFilename := fileName asLowercase.
       
  2345 
       
  2346         select := true.
       
  2347 
       
  2348         "some heuristics - my personal preferences ...
       
  2349          (actually this should come from a configfile)"
       
  2350 
       
  2351         (fileName endsWith:'akefile') ifTrue:[
       
  2352             aBox initialText:'make target' selectFrom:6 to:11.
       
  2353             ^ self
       
  2354         ].
       
  2355         (lcFilename endsWith:'tar.z') ifTrue:[
       
  2356             cmd := 'zcat %1 | tar tvf -'.
       
  2357             select := false.
       
  2358         ].
       
  2359         (fileName endsWith:'.taz') ifTrue:[
       
  2360             aBox initialText:'zcat %1 | tar tvf -'.
       
  2361             select := false.
       
  2362         ].
       
  2363         (fileName endsWith:'.tar') ifTrue:[
       
  2364             cmd := 'tar tvf %1'.
       
  2365             select := 7.
       
  2366         ].
       
  2367         (fileName endsWith:'.zoo') ifTrue:[
       
  2368             cmd := 'zoo -list %1'.
       
  2369             select := 9.
       
  2370         ].
       
  2371         (lcFilename endsWith:'.zip') ifTrue:[
       
  2372             cmd := 'unzip -l %1'.
       
  2373             select := 8.
       
  2374         ].
       
  2375         (lcFilename endsWith:'.z') ifTrue:[
       
  2376             cmd := 'uncompress %1'
       
  2377         ].
       
  2378         (fileName endsWith:'tar.gz') ifTrue:[
       
  2379             cmd := ('gunzip < %1 | tar tvf -' ).
       
  2380             select := false.
       
  2381         ].
       
  2382         (fileName endsWith:'.tgz') ifTrue:[
       
  2383             cmd := ('gunzip < %1 | tar tvf -' ).
       
  2384             select := false.
       
  2385         ].
       
  2386         (fileName endsWith:'.gz') ifTrue:[
       
  2387             cmd := 'gunzip %1'.
       
  2388         ].
       
  2389         (lcFilename endsWith:'.html') ifTrue:[
       
  2390             cmd := 'netscape %1'
       
  2391         ].
       
  2392         (lcFilename endsWith:'.htm') ifTrue:[
       
  2393             cmd := 'netscape %1'
       
  2394         ].
       
  2395         (fileName endsWith:'.uue') ifTrue:[
       
  2396             cmd := 'uudecode %1'
       
  2397         ].
       
  2398         (fileName endsWith:'.c') ifTrue:[
       
  2399             cmd := 'cc -c %1'.
       
  2400             select := 5.
       
  2401         ].
       
  2402         (fileName endsWith:'.cc') ifTrue:[
       
  2403             cmd := 'g++ -c %1'.
       
  2404             select := 6.
       
  2405         ].
       
  2406         (fileName endsWith:'.C') ifTrue:[
       
  2407             cmd := 'g++ -c %1'.
       
  2408             select := 6.
       
  2409         ].
       
  2410         (fileName endsWith:'.xbm') ifTrue:[
       
  2411             cmd := 'bitmap %1'
       
  2412         ].
       
  2413         (lcFilename endsWith:'.ps') ifTrue:[
       
  2414             cmd := 'ghostview %1'
       
  2415         ].
       
  2416         ((fileName endsWith:'.1') 
       
  2417         or:[fileName endsWith:'.man']) ifTrue:[
       
  2418             cmd := 'nroff -man %1'.
       
  2419             select := 10.
       
  2420         ].
       
  2421 
       
  2422         cmd isNil ifTrue:[
       
  2423             DefaultCommandPerSuffix isNil ifTrue:[
       
  2424                 cmd := '<cmd>'
       
  2425             ] ifFalse:[
       
  2426                 cmd := DefaultCommandPerSuffix 
       
  2427                         at:(lcFilename asFilename suffix)
       
  2428                         ifAbsent:'<cmd>'.
       
  2429             ].
       
  2430             cmd := cmd , ' %1'.
       
  2431         ].
       
  2432 
       
  2433         cmd := cmd bindWith:fileName.
       
  2434         select == false ifTrue:[
       
  2435             aBox initialText:cmd
       
  2436         ] ifFalse:[
       
  2437             select isInteger ifFalse:[
       
  2438                 select := (cmd indexOf:Character space ifAbsent:[cmd size + 1]) - 1.
       
  2439             ].
       
  2440             aBox initialText:cmd selectFrom:1 to:select
       
  2441         ]
       
  2442     ]
       
  2443 
       
  2444     "Modified: 4.4.1997 / 12:26:40 / cg"
       
  2445 !
       
  2446 
       
  2447 onlyOneSelection
       
  2448     "show a warning, that only one file must be selected for
       
  2449      this operation"
       
  2450 
       
  2451     self warn:'exactly one file must be selected !!'
       
  2452 !
       
  2453 
       
  2454 selectedFilesDo:aBlock
       
  2455     "evaluate aBlock on all selected files;
       
  2456      show a wait cursor while doing this"
       
  2457 
       
  2458     |sel|
       
  2459 
       
  2460     sel := fileListView selection.
       
  2461     sel notNil ifTrue:[
       
  2462         self withWaitCursorDo:[
       
  2463             sel do:[:aSelectionIndex |
       
  2464                 aBlock value:(fileList at:aSelectionIndex )
       
  2465             ]
       
  2466         ]
       
  2467     ]
       
  2468 
       
  2469 !
       
  2470 
       
  2471 setCurrentDirectory:aPathName
       
  2472     "setup for another directory"
       
  2473 
       
  2474     |newDirectory|
       
  2475 
       
  2476     aPathName isEmpty ifTrue:[^ self].
       
  2477     (currentDirectory isDirectory:aPathName) ifTrue:[
       
  2478         newDirectory := FileDirectory directoryNamed:aPathName in:currentDirectory.
       
  2479         newDirectory notNil ifTrue:[
       
  2480             self currentDirectory:newDirectory pathName.
       
  2481             currentFileName notNil ifTrue:[
       
  2482                 fileListView contents:nil.
       
  2483                 currentFileName := nil.
       
  2484             ] ifFalse:[
       
  2485                 fileListView setSelection:nil.
       
  2486                 fileListView scrollToTop.
       
  2487             ].
       
  2488             self updateCurrentDirectory.
       
  2489             self showInfo.
       
  2490         ]
       
  2491     ]
       
  2492 
       
  2493     "Modified: 21.9.1995 / 11:22:45 / claus"
       
  2494     "Modified: 25.5.1996 / 12:27:01 / cg"
       
  2495 !
       
  2496 
       
  2497 show:something
       
  2498     "show something in subview and undef acceptAction"
       
  2499 
       
  2500     subView contents:something.
       
  2501     subView acceptAction:nil.
       
  2502     subView modified:false.
       
  2503     currentFileName := nil
       
  2504 !
       
  2505 
       
  2506 showAlert:aString with:anErrorString
       
  2507     "show an alertbox, displaying the last Unix-error"
       
  2508 
       
  2509     |msg|
       
  2510 
       
  2511     anErrorString isNil ifTrue:[
       
  2512         msg := aString
       
  2513     ] ifFalse:[
       
  2514         msg := aString , '\\(' , anErrorString , ')'
       
  2515     ].
       
  2516     self warn:msg withCRs
       
  2517 !
  2736 !
  2518 
  2737 
  2519 showInfo
  2738 showInfo
  2520     "show directory info when dir has changed"
  2739     "show directory info when dir has changed"
  2521 
  2740 
  2549     ] ifFalse:[
  2768     ] ifFalse:[
  2550         n := (size * 10 // 1024 // 1024 / 10.0).
  2769         n := (size * 10 // 1024 // 1024 / 10.0).
  2551         unitString := ' Mb'
  2770         unitString := ' Mb'
  2552     ].
  2771     ].
  2553     ^ (n printStringLeftPaddedTo:5) , unitString.
  2772     ^ (n printStringLeftPaddedTo:5) , unitString.
  2554 !
       
  2555 
       
  2556 updateCurrentDirectoryIfChanged
       
  2557     (currentDirectory timeOfLastChange > timeOfLastCheck) ifTrue:[
       
  2558         self updateCurrentDirectory
       
  2559     ]
       
  2560 
       
  2561     "Modified: 19.4.1997 / 15:30:03 / cg"
       
  2562 !
       
  2563 
       
  2564 validateFontEncodingFor:newEncoding ask:ask
       
  2565     "if required, query user if he/she wants to change to another font,
       
  2566      which is able to display text encoded as specified by newEncoding"
       
  2567 
       
  2568     |fontsEncoding msg filter f defaultFont|
       
  2569 
       
  2570     fontsEncoding := subView font encoding.
       
  2571 
       
  2572     ((newEncoding == #jis7) or:[newEncoding == #euc]) ifTrue:[
       
  2573         (fontsEncoding notNil and:[fontsEncoding startsWith:'jis']) ifFalse:[
       
  2574             msg := 'switch to a JIS encoded font ?'.
       
  2575             filter := [:f | |coding|
       
  2576                             (coding := f encoding) notNil 
       
  2577                             and:['jis*' match:coding]].
       
  2578         ]
       
  2579     ].
       
  2580     (newEncoding == #gb) ifTrue:[
       
  2581         (fontsEncoding notNil and:[fontsEncoding startsWith:'gb']) ifFalse:[
       
  2582             msg := 'switch to a GB encoded font ?'.
       
  2583             filter := [:f | |coding|
       
  2584                             (coding := f encoding) notNil 
       
  2585                             and:['gb*' match:coding]].
       
  2586         ]
       
  2587     ].
       
  2588     (newEncoding == #big5) ifTrue:[
       
  2589         (fontsEncoding notNil and:[fontsEncoding startsWith:'big5']) ifFalse:[
       
  2590             msg := 'switch to a BIG-5 encoded font ?'.
       
  2591             filter := [:f | |coding|
       
  2592                             (coding := f encoding) notNil 
       
  2593                             and:['big5*' match:coding]].
       
  2594         ]
       
  2595     ].
       
  2596     (newEncoding == #ksc) ifTrue:[
       
  2597         (fontsEncoding notNil and:[fontsEncoding startsWith:'ksc']) ifFalse:[
       
  2598             msg := 'switch to a KSC encoded font ?'.
       
  2599             filter := [:f | |coding|
       
  2600                             (coding := f encoding) notNil 
       
  2601                             and:['ksc*' match:coding]].
       
  2602         ]
       
  2603     ] ifFalse:[
       
  2604         fontsEncoding notNil ifTrue:[
       
  2605             ((fontsEncoding startsWith:'jis')
       
  2606             or:[(fontsEncoding startsWith:'gb')
       
  2607             or:[(fontsEncoding startsWith:'ksc')
       
  2608             or:[(fontsEncoding startsWith:'big5')]]])
       
  2609             ifTrue:[
       
  2610                 msg := 'switch back to an ASCII encoded font ?'.
       
  2611                 filter := [:f | |coding|
       
  2612                                 (coding := f encoding) notNil 
       
  2613                                 and:[('ascii' match:coding)
       
  2614                                      or:['iso*' match:coding]]].
       
  2615                 defaultFont := TextView defaultFont
       
  2616             ] ifFalse:[
       
  2617                 (fontsEncoding notNil and:[fontsEncoding startsWith:'iso8859']) ifTrue:[
       
  2618                     msg := 'switch to a ''' , newEncoding , ''' encoded font ?'.
       
  2619                     filter := [:f | |coding|
       
  2620                                     (coding := f encoding) notNil 
       
  2621                                     and:[newEncoding asLowercase = coding asLowercase]].
       
  2622                 ].
       
  2623             ].
       
  2624         ]
       
  2625     ].
       
  2626 
       
  2627     msg isNil ifTrue:[
       
  2628         "/ mhmh - can be represented in current font
       
  2629     ].
       
  2630 
       
  2631     msg notNil ifTrue:[
       
  2632         defaultFont isNil ifTrue:[
       
  2633             defaultFont := device 
       
  2634                                 listOfAvailableFonts 
       
  2635                                     detect:[:f | filter value:f]
       
  2636                                     ifNone:nil.
       
  2637             defaultFont isNil ifTrue:[
       
  2638                 self warn:'your display does not seem to provide any ' , newEncoding , '-encoded font.'.
       
  2639                 ^ self.
       
  2640             ]
       
  2641         ].
       
  2642 
       
  2643         (ask not or:[self confirm:(resources string:msg) withCRs])
       
  2644         ifTrue:[
       
  2645             f := FontPanel 
       
  2646                 fontFromUserInitial:defaultFont
       
  2647                               title:(resources string:'font selection')
       
  2648                              filter:filter.
       
  2649             f notNil ifTrue:[
       
  2650                 subView font:f
       
  2651             ]
       
  2652         ]
       
  2653     ]
       
  2654 
       
  2655     "Created: 26.10.1996 / 12:06:54 / cg"
       
  2656 !
       
  2657 
       
  2658 withoutHiddenFiles:aCollection
       
  2659     "remove hidden files (i.e. those that start with '.') from
       
  2660      the list in aCollection"
       
  2661 
       
  2662     |newCollection|
       
  2663 
       
  2664     newCollection := aCollection species new.
       
  2665     aCollection do:[:fname |
       
  2666         |ignore|
       
  2667 
       
  2668         ignore := false.
       
  2669 
       
  2670         ((fname startsWith:'.') and:[fname ~= '..']) ifTrue:[
       
  2671             showDotFiles ifFalse:[
       
  2672                 ignore := true
       
  2673             ]
       
  2674         ].
       
  2675         ignore ifFalse:[
       
  2676             newCollection add:fname
       
  2677         ]
       
  2678     ].
       
  2679     ^ newCollection
       
  2680 
       
  2681     "Modified: 21.2.1996 / 01:33:18 / cg"
       
  2682 ! !
  2773 ! !
  2683 
  2774 
  2684 !FileBrowser methodsFor:'private - actions'!
  2775 !FileBrowser methodsFor:'private - file-I/O'!
  2685 
       
  2686 binaryFileAction:aFilename
       
  2687     "for some binary files, if double clicked, we can do some useful
       
  2688      action ..."
       
  2689 
       
  2690     (currentDirectory pathName , '/' , aFilename) asFilename isExecutable ifTrue:[
       
  2691         (OperatingSystem executeCommand:'cd ',currentDirectory pathName, '; ',aFilename)
       
  2692         ifTrue:[^true].
       
  2693     ].
       
  2694     ^ self imageAction:aFilename
       
  2695 
       
  2696     "Modified: 19.6.1996 / 09:44:07 / cg"
       
  2697 !
       
  2698 
       
  2699 imageAction:aFilename
       
  2700     "for some image files, if double clicked, we can do some useful
       
  2701      action ..."
       
  2702 
       
  2703     |img|
       
  2704 
       
  2705     (Image isImageFileSuffix:(aFilename asFilename suffix))
       
  2706     ifTrue:[
       
  2707         img := Image fromFile:(currentDirectory pathName , '/' , aFilename).
       
  2708         img notNil ifTrue:[
       
  2709             img inspect.
       
  2710             ^ true
       
  2711         ]
       
  2712     ].
       
  2713     ^ false
       
  2714 
       
  2715     "Created: 19.6.1996 / 09:43:50 / cg"
       
  2716     "Modified: 18.4.1997 / 14:56:04 / cg"
       
  2717 !
       
  2718 
       
  2719 nonBinaryFileAction:aFilename
       
  2720     "for some nonBinary files, if double clicked, we can do some useful
       
  2721      action ..."
       
  2722 
       
  2723     |fullPath lcName|
       
  2724 
       
  2725     fullPath := currentDirectory pathName , '/' , aFilename.
       
  2726     lcName := aFilename asLowercase.
       
  2727     ((lcName endsWith:'.htm') or:[lcName endsWith:'.html']) ifTrue:[
       
  2728         HTMLDocumentView openOn:fullPath.
       
  2729         ^ true
       
  2730     ].
       
  2731 
       
  2732     OperatingSystem isUNIXlike ifTrue:[
       
  2733         (#('.man' '.1' '.2' '.3') findFirst:[:suff | aFilename endsWith:suff]) ~~ 0 
       
  2734         ifTrue:[
       
  2735              HTMLDocumentView openFullOnText:(HTMLDocGenerator manPageForFile:fullPath).
       
  2736             ^ true
       
  2737         ]
       
  2738     ].
       
  2739     ^ self imageAction:aFilename
       
  2740 
       
  2741     "Created: 19.6.1996 / 09:36:38 / cg"
       
  2742     "Modified: 4.4.1997 / 10:49:00 / cg"
       
  2743 ! !
       
  2744 
       
  2745 !FileBrowser methodsFor:'private - presentation'!
       
  2746 
       
  2747 defineTabulatorsForLongList
       
  2748     "define the tabs for the long list"
       
  2749 
       
  2750     tabSpec := TabulatorSpecification new.
       
  2751     tabSpec unit:#inch.
       
  2752 "/  tabSpec positions:#(0     0.25    2.3   4.3    5.3    6.0      6.5).
       
  2753     tabSpec widths:   #(0.25   2      2.0     1      0.5  0.5      1"any").
       
  2754     "                   icon  name   mode  owner  group  size     type"
       
  2755     tabSpec align:    #(#left #left  #left #right #right #decimal #left).
       
  2756     tabSpec addDependent:self.
       
  2757 
       
  2758     tabRulerView tabulatorSpecification:tabSpec.
       
  2759 
       
  2760     "Modified: 17.4.1997 / 02:56:07 / cg"
       
  2761 !
       
  2762 
       
  2763 defineTabulatorsForShortList
       
  2764     "define the tabs for the short list"
       
  2765 
       
  2766     tabSpec := TabulatorSpecification new.
       
  2767     tabSpec unit:#inch.
       
  2768 "/  tabSpec positions:#(0     0.25 ).
       
  2769     tabSpec widths:   #(0.25   2   ).
       
  2770     "                   icon  name"
       
  2771     tabSpec align:    #(#left #left).
       
  2772     tabSpec addDependent:self.
       
  2773 
       
  2774     tabRulerView tabulatorSpecification:tabSpec.
       
  2775 
       
  2776     "Created: 17.4.1997 / 02:51:41 / cg"
       
  2777     "Modified: 17.4.1997 / 02:55:17 / cg"
       
  2778 !
       
  2779 
       
  2780 iconForFile:aFilenameString
       
  2781     "given a fileName, return an appropriate icon"
       
  2782 
       
  2783     |f suff i key|
       
  2784 
       
  2785     f := currentDirectory asFilename construct:aFilenameString.
       
  2786     f isDirectory ifTrue:[
       
  2787         f isSymbolicLink ifTrue:[
       
  2788             key := #directoryLink
       
  2789         ] ifFalse:[
       
  2790             key := #directory.
       
  2791             (f isReadable not
       
  2792             or:[f isExecutable not]) ifTrue:[
       
  2793                 key := #directoryLocked
       
  2794             ].
       
  2795         ]
       
  2796     ] ifFalse:[
       
  2797         f isSymbolicLink ifTrue:[
       
  2798             key := #fileLink
       
  2799         ] ifFalse:[
       
  2800             key := #file.
       
  2801             (f isReadable not) ifTrue:[
       
  2802                 key := #fileLocked
       
  2803             ] ifFalse:[
       
  2804                 (Image isImageFileSuffix:(f suffix)) ifTrue:[
       
  2805                     key := #imageFile
       
  2806                 ]
       
  2807             ].
       
  2808         ].
       
  2809     ].
       
  2810 
       
  2811     icons isNil ifTrue:[
       
  2812         icons := IdentityDictionary new
       
  2813     ].
       
  2814 
       
  2815     i := icons at:key ifAbsent:nil.
       
  2816     i isNil ifTrue:[
       
  2817         i := Icons at:key ifAbsent:nil.
       
  2818         i notNil ifTrue:[
       
  2819             i := i on:device.
       
  2820             icons at:key put:i.
       
  2821         ]
       
  2822     ].
       
  2823     ^ i
       
  2824 
       
  2825     "Modified: 18.4.1997 / 15:18:38 / cg"
       
  2826 !
       
  2827 
       
  2828 stopUpdateProcess
       
  2829     Processor removeTimedBlock:checkBlock.
       
  2830     listUpdateProcess notNil ifTrue:[
       
  2831         listUpdateProcess terminate.
       
  2832         listUpdateProcess := nil.
       
  2833     ].
       
  2834 
       
  2835     "Created: 19.4.1997 / 13:51:34 / cg"
       
  2836 !
       
  2837 
       
  2838 updateCurrentDirectory
       
  2839     "update listView with directory contents"
       
  2840 
       
  2841     "the code below may look somewhat complex -
       
  2842      it reads the directory first for the names,
       
  2843      then (in followup sweeps over the files) gets the
       
  2844      files type, info and icon in a forked subprocess. 
       
  2845      This makes the Filebrowsers list update faster, since the fileInfo 
       
  2846      (i.e. stat-calls) may take long - especially on NFS-mounted directories.
       
  2847      The file reading is done at lower priority, to let user continue
       
  2848      his work in other views. However, to be fair to other fileBrowser,
       
  2849      which may also read directories at low prio, give up the processor
       
  2850      after every entry. This shares the cpu among all fileBrowsers;
       
  2851      Therefore, browsers which read short directories will finish first.
       
  2852      ST/X users love this behavior ;-)
       
  2853     "
       
  2854 
       
  2855     self withReadCursorDo:[
       
  2856         |files matchPattern|
       
  2857 
       
  2858         self stopUpdateProcess.
       
  2859 
       
  2860         timeOfLastCheck := AbsoluteTime now.
       
  2861 
       
  2862         files := currentDirectory asOrderedCollection.
       
  2863 
       
  2864         "/ show files which are either directories
       
  2865         "/ or match the current pattern
       
  2866 
       
  2867         matchPattern := filterField contents.
       
  2868         (matchPattern notNil and:[
       
  2869          matchPattern isEmpty not and:[
       
  2870          matchPattern ~= '*']]) ifTrue:[
       
  2871              files := files select:[:aName | 
       
  2872                          ((currentDirectory typeOf:aName) == #directory)
       
  2873                          or:[matchPattern compoundMatch:aName]
       
  2874                       ].
       
  2875         ].
       
  2876 
       
  2877         files sort.
       
  2878 
       
  2879         files size == 0 ifTrue:[
       
  2880             self information:('directory ', currentDirectory pathName, ' vanished').
       
  2881             ^ self
       
  2882         ].
       
  2883         files := self withoutHiddenFiles:files.
       
  2884         fileList := files copy.
       
  2885 
       
  2886         "
       
  2887          this is a time consuming operation (especially, if reading an
       
  2888          NFS-mounted directory); therefore, start a low prio process,
       
  2889          which fills in the remaining fields in the fileList ...
       
  2890         "
       
  2891 
       
  2892         listUpdateProcess := [
       
  2893             |prevUid prevGid fileNameString nameString groupString 
       
  2894              modeString info line len list
       
  2895              anyImages passDone lineIndex aFileName
       
  2896              entry typ f p typeString done endIndex 
       
  2897              state stopAtEnd nextState img prevFirstLine prevLastLine
       
  2898              numVisible|
       
  2899 
       
  2900             tabSpec isNil ifTrue:[
       
  2901                 showLongList ifTrue:[
       
  2902                     self defineTabulatorsForLongList
       
  2903                 ] ifFalse:[
       
  2904                     self defineTabulatorsForShortList
       
  2905                 ].
       
  2906             ].
       
  2907 
       
  2908             "/
       
  2909             "/ first show all the names - this can be done fast ...
       
  2910             "/
       
  2911             list := files collect:[:fileName |
       
  2912                         |entry|
       
  2913 
       
  2914                         entry := MultiColListEntry new.
       
  2915                         entry tabulatorSpecification:tabSpec.
       
  2916                         entry colAt:1 put:nil.
       
  2917                         entry colAt:2 put:fileName.
       
  2918                     ].
       
  2919 
       
  2920             fileListView setList:list expandTabs:false.
       
  2921             passDone := Array new:list size withAll:0.
       
  2922 
       
  2923             "/
       
  2924             "/ then walk over the files, adding more info
       
  2925             "/ (since we have to stat each file, this may take a while longer)
       
  2926             "/ Visible items are always filled first.
       
  2927 
       
  2928             "/
       
  2929             "/ the state machine
       
  2930             "/
       
  2931             nextState := IdentityDictionary new.
       
  2932             showLongList ifTrue:[
       
  2933                 nextState add:(#visibleIcons -> #visibleAttributes).
       
  2934                 nextState add:(#visibleAttributes -> #visibleTypes).
       
  2935                 nextState add:(#visibleTypes -> #visibleImages).
       
  2936                 nextState add:(#visibleImages -> #nextPageIcons).
       
  2937 
       
  2938                 nextState add:(#nextPageIcons -> #nextPageAttributes).
       
  2939                 nextState add:(#nextPageAttributes -> #nextPageTypes).
       
  2940                 nextState add:(#nextPageTypes -> #nextPageImages).
       
  2941                 nextState add:(#nextPageImages -> #previousPageIcons).
       
  2942 
       
  2943                 nextState add:(#previousPageIcons -> #previousPageAttributes).
       
  2944                 nextState add:(#previousPageAttributes -> #previousPageTypes).
       
  2945                 nextState add:(#previousPageTypes -> #previousPageImages).
       
  2946                 nextState add:(#previousPageImages -> #remainingIcons).
       
  2947 
       
  2948                 nextState add:(#remainingIcons -> #remainingAttributes).
       
  2949                 nextState add:(#remainingAttributes -> #remainingTypes).
       
  2950                 nextState add:(#remainingTypes -> #remainingImages).
       
  2951                 nextState add:(#remainingImages -> nil).
       
  2952             ] ifFalse:[
       
  2953                 nextState add:(#visibleIcons -> #nextPageIcons).
       
  2954                 nextState add:(#nextPageIcons -> #previousPageIcons).
       
  2955                 nextState add:(#previousPageIcons -> #remainingIcons).
       
  2956                 nextState add:(#remainingIcons -> nil).
       
  2957             ].
       
  2958 
       
  2959             anyImages := false.
       
  2960 
       
  2961             lineIndex := prevFirstLine := fileListView firstLineShown.
       
  2962             endIndex := prevLastLine := fileListView lastLineShown.
       
  2963             endIndex := endIndex min:(files size).
       
  2964             state := #visibleIcons.
       
  2965 
       
  2966             done := false.
       
  2967             [done] whileFalse:[
       
  2968                 "/
       
  2969                 "/ if multiple FileBrowsers are reading, let others
       
  2970                 "/ make some progress too
       
  2971                 "/
       
  2972                 Processor yield.
       
  2973 
       
  2974                 "/
       
  2975                 "/ could be destroyed in the meanwhile ...
       
  2976                 "/
       
  2977                 realized ifFalse:[
       
  2978                     listUpdateProcess := nil.
       
  2979                     Processor activeProcess terminate
       
  2980                 ].
       
  2981 
       
  2982                 ((prevFirstLine ~~ fileListView firstLineShown)
       
  2983                 or:[prevLastLine ~~ fileListView lastLineShown]) ifTrue:[
       
  2984                     "/ start all over again
       
  2985                     lineIndex := prevFirstLine := fileListView firstLineShown.
       
  2986                     endIndex := prevLastLine := fileListView lastLineShown.
       
  2987                     endIndex := endIndex min:(files size).
       
  2988                     state := #visibleIcons.
       
  2989                 ].
       
  2990 
       
  2991                 (lineIndex between:1 and:(files size)) ifTrue:[
       
  2992 
       
  2993                     "/
       
  2994                     "/ expand the next entry ...
       
  2995                     "/
       
  2996                     aFileName := files at:lineIndex.
       
  2997                     entry := fileListView at:lineIndex.
       
  2998 
       
  2999                     (state endsWith:'Icons') ifTrue:[
       
  3000                         "/
       
  3001                         "/ pass 1 - icons
       
  3002                         "/
       
  3003                         (passDone at:lineIndex) < 1 ifTrue:[
       
  3004                             ((currentDirectory isDirectory:aFileName) and:[
       
  3005                             (aFileName ~= '..') and:[aFileName ~= '.']]) ifTrue:[
       
  3006                                 fileNameString := aFileName , ' ...'
       
  3007                             ] ifFalse:[
       
  3008                                 fileNameString := aFileName
       
  3009                             ].
       
  3010 
       
  3011                             showLongList ifTrue:[
       
  3012                                 len := fileNameString size.
       
  3013                                 (len > 20) ifTrue:[
       
  3014                                     fileNameString := (fileNameString contractTo:20)
       
  3015                                 ].
       
  3016                             ].
       
  3017 
       
  3018                             entry colAt:1 put:(self iconForFile:aFileName).
       
  3019                             entry colAt:2 put:fileNameString.
       
  3020 
       
  3021                             fileListView at:lineIndex put:entry.
       
  3022 
       
  3023                             anyImages ifFalse:[
       
  3024                                 (Image isImageFileSuffix:(aFileName asFilename suffix))
       
  3025                                 ifTrue:[
       
  3026                                     anyImages := true
       
  3027                                 ]
       
  3028                             ].
       
  3029                             passDone at:lineIndex put:1
       
  3030                         ]
       
  3031                     ].
       
  3032 
       
  3033                     (state endsWith:'Attributes') ifTrue:[
       
  3034                         "/
       
  3035                         "/ pass 2 - everything except fileType (which takes very long)
       
  3036                         "/
       
  3037                         (passDone at:lineIndex) < 2 ifTrue:[
       
  3038 
       
  3039                             info := currentDirectory infoOf:aFileName.
       
  3040                             info isNil ifTrue:[
       
  3041                                 "not accessable - usually a symlink,
       
  3042                                  to a nonexisting/nonreadable file
       
  3043                                 "
       
  3044                                 f := currentDirectory asFilename:aFileName.
       
  3045                                 f isSymbolicLink ifTrue:[
       
  3046                                     p := f linkInfo path.    
       
  3047                                     typeString := 'broken symbolic link to ' , p
       
  3048                                 ] ifFalse:[
       
  3049                                     typeString := 'unknwon (bad symbolic link ?)'
       
  3050                                 ].
       
  3051                                 entry colAt:7 put:typeString.
       
  3052                             ] ifFalse:[
       
  3053                                 typ := (info type).
       
  3054 
       
  3055                                 modeString := self getModeString:(info at:#mode)
       
  3056                                                             with:#( '' $r $w $x 
       
  3057                                                                     '  ' $r $w $x 
       
  3058                                                                     '  ' $r $w $x ).
       
  3059                                 entry colAt:3 put:modeString.
       
  3060 
       
  3061                                 ((info uid) ~~ prevUid) ifTrue:[
       
  3062                                     prevUid := (info uid).
       
  3063                                     nameString := OperatingSystem getUserNameFromID:prevUid.
       
  3064                                     nameString := nameString , (String new:(10 - nameString size))
       
  3065                                 ].
       
  3066                                 entry colAt:4 put:nameString withoutSpaces.
       
  3067 
       
  3068                                 ((info gid) ~~ prevGid) ifTrue:[
       
  3069                                     prevGid := (info gid).
       
  3070                                     groupString := OperatingSystem getGroupNameFromID:prevGid.
       
  3071                                     groupString := groupString , (String new:(10 - groupString size))
       
  3072                                 ].
       
  3073                                 entry colAt:5 put:groupString withoutSpaces.
       
  3074 
       
  3075                                 (typ == #regular) ifTrue:[
       
  3076                                     entry colAt:6 put:(self sizePrintString:(info size)).
       
  3077                                 ].
       
  3078 
       
  3079                                 f := currentDirectory asFilename:aFileName.
       
  3080                                 f isSymbolicLink ifTrue:[
       
  3081                                     p := f linkInfo path.    
       
  3082                                     typeString := 'symbolic link to ' , p
       
  3083                                 ] ifFalse:[
       
  3084                                     typeString := typ asString
       
  3085                                 ].
       
  3086                                 entry colAt:7 put:typeString
       
  3087                             ].
       
  3088                             fileListView at:lineIndex put:entry.
       
  3089                             passDone at:lineIndex put:2.
       
  3090                         ].
       
  3091                     ].
       
  3092 
       
  3093                     (state endsWith:'Types') ifTrue:[
       
  3094                         "/
       
  3095                         "/ pass 3: add fileType
       
  3096                         "/
       
  3097                         (passDone at:lineIndex) < 3 ifTrue:[
       
  3098                             info := currentDirectory infoOf:aFileName.
       
  3099                             info notNil ifTrue:[
       
  3100                                 f := currentDirectory asFilename:aFileName.
       
  3101                                 f isSymbolicLink ifFalse:[
       
  3102                                     (Image isImageFileSuffix:(f suffix)) ifFalse:[
       
  3103                                         typeString := f fileType.
       
  3104 
       
  3105                                         entry colAt:7 put:typeString.
       
  3106                                         fileListView at:lineIndex put:entry
       
  3107                                     ].
       
  3108                                 ].
       
  3109                             ].
       
  3110 
       
  3111                             passDone at:lineIndex put:3
       
  3112                         ].
       
  3113                     ].
       
  3114 
       
  3115                     (state endsWith:'Images') ifTrue:[
       
  3116                         "/
       
  3117                         "/ pass 4: read images
       
  3118                         "/
       
  3119                         (passDone at:lineIndex) < 4 ifTrue:[
       
  3120                             f := currentDirectory asFilename construct:aFileName.
       
  3121                             (Image isImageFileSuffix:(f suffix)) ifTrue:[
       
  3122                                 f isDirectory ifFalse:[
       
  3123                                     img := Image fromFile:(f pathName).
       
  3124                                     img notNil ifTrue:[
       
  3125                                         img := img magnifiedTo:16@16.
       
  3126                                         img := img on:self device.
       
  3127                                         entry colAt:7 put:img.
       
  3128                                         fileListView at:lineIndex put:entry
       
  3129                                     ]
       
  3130                                 ]
       
  3131                             ].
       
  3132                             passDone at:lineIndex put:4
       
  3133                         ].
       
  3134                     ].
       
  3135                 ].
       
  3136 
       
  3137                 "/
       
  3138                 "/ advance to the next line
       
  3139                 "/
       
  3140                 lineIndex := lineIndex + 1.
       
  3141                 lineIndex > endIndex ifTrue:[
       
  3142                     "/ finished this round ...
       
  3143                     "/ see what we are going for ...
       
  3144                     numVisible := (fileListView lastLineShown - fileListView firstLineShown + 1).
       
  3145 
       
  3146                     state := nextState at:state ifAbsent:nil.
       
  3147 
       
  3148                     state isNil ifTrue:[
       
  3149                         done := true
       
  3150                     ] ifFalse:[
       
  3151                         (state startsWith:'visible') ifTrue:[
       
  3152                             lineIndex := fileListView firstLineShown.
       
  3153                             endIndex := fileListView lastLineShown.
       
  3154                             endIndex := endIndex min:(files size).
       
  3155                         ] ifFalse:[
       
  3156                             (state startsWith:'nextPage') ifTrue:[
       
  3157                                 lineIndex := fileListView lastLineShown + 1.
       
  3158                                 endIndex := lineIndex + numVisible.
       
  3159                                 endIndex := endIndex min:(files size).
       
  3160                                 lineIndex := lineIndex min:(files size).
       
  3161                             ] ifFalse:[
       
  3162                                 (state startsWith:'previousPage') ifTrue:[
       
  3163                                     endIndex := fileListView firstLineShown - 1.
       
  3164                                     lineIndex := endIndex - numVisible.
       
  3165                                     lineIndex := lineIndex max:1.
       
  3166                                     endIndex := endIndex min:(files size).
       
  3167                                     endIndex := endIndex max:1.
       
  3168                                 ] ifFalse:[ 
       
  3169                                     "/ remaining
       
  3170                                     lineIndex := 1.
       
  3171                                     endIndex := files size.
       
  3172                                 ]
       
  3173                             ]
       
  3174                         ]
       
  3175                     ]
       
  3176                 ]
       
  3177             ].
       
  3178 
       
  3179             listUpdateProcess := nil.
       
  3180 
       
  3181         ] forkAt:(Processor activePriority - 1).
       
  3182 
       
  3183         "
       
  3184          install a new check after some time
       
  3185         "
       
  3186         Processor addTimedBlock:checkBlock afterSeconds:checkDelta
       
  3187     ]
       
  3188 
       
  3189     "Modified: 21.9.1995 / 11:40:23 / claus"
       
  3190     "Modified: 21.4.1997 / 15:01:27 / cg"
       
  3191 ! !
       
  3192 
       
  3193 !FileBrowser methodsFor:'private-file-I/O'!
       
  3194 
  2776 
  3195 readFile:fileName
  2777 readFile:fileName
  3196     "read in the file, answer its contents as StringCollection"
  2778     "read in the file, answer its contents as StringCollection"
  3197 
  2779 
  3198     ^ self readFile:fileName lineDelimiter:Character cr encoding:nil
  2780     ^ self readFile:fileName lineDelimiter:Character cr encoding:nil
  3443 
  3025 
  3444     "Created: 22.2.1996 / 15:03:10 / cg"
  3026     "Created: 22.2.1996 / 15:03:10 / cg"
  3445     "Modified: 22.2.1996 / 15:08:31 / cg"
  3027     "Modified: 22.2.1996 / 15:08:31 / cg"
  3446 ! !
  3028 ! !
  3447 
  3029 
       
  3030 !FileBrowser methodsFor:'private - presentation'!
       
  3031 
       
  3032 defineTabulatorsForLongList
       
  3033     "define the tabs for the long list"
       
  3034 
       
  3035     tabSpec := TabulatorSpecification new.
       
  3036     tabSpec unit:#inch.
       
  3037 "/  tabSpec positions:#(0     0.25    2.3   4.3    5.3    6.0      6.5).
       
  3038     tabSpec widths:   #(0.25   2      2.0     1      0.5  0.5      1"any").
       
  3039     "                   icon  name   mode  owner  group  size     type"
       
  3040     tabSpec align:    #(#left #left  #left #right #right #decimal #left).
       
  3041     tabSpec addDependent:self.
       
  3042 
       
  3043     tabRulerView tabulatorSpecification:tabSpec.
       
  3044 
       
  3045     "Modified: 17.4.1997 / 02:56:07 / cg"
       
  3046 !
       
  3047 
       
  3048 defineTabulatorsForShortList
       
  3049     "define the tabs for the short list"
       
  3050 
       
  3051     tabSpec := TabulatorSpecification new.
       
  3052     tabSpec unit:#inch.
       
  3053 "/  tabSpec positions:#(0     0.25 ).
       
  3054     tabSpec widths:   #(0.25   2   ).
       
  3055     "                   icon  name"
       
  3056     tabSpec align:    #(#left #left).
       
  3057     tabSpec addDependent:self.
       
  3058 
       
  3059     tabRulerView tabulatorSpecification:tabSpec.
       
  3060 
       
  3061     "Created: 17.4.1997 / 02:51:41 / cg"
       
  3062     "Modified: 17.4.1997 / 02:55:17 / cg"
       
  3063 !
       
  3064 
       
  3065 iconForFile:aFilenameString
       
  3066     "given a fileName, return an appropriate icon"
       
  3067 
       
  3068     |f suff i key|
       
  3069 
       
  3070     f := currentDirectory asFilename construct:aFilenameString.
       
  3071     f isDirectory ifTrue:[
       
  3072         f isSymbolicLink ifTrue:[
       
  3073             key := #directoryLink
       
  3074         ] ifFalse:[
       
  3075             key := #directory.
       
  3076             (f isReadable not
       
  3077             or:[f isExecutable not]) ifTrue:[
       
  3078                 key := #directoryLocked
       
  3079             ].
       
  3080         ]
       
  3081     ] ifFalse:[
       
  3082         f isSymbolicLink ifTrue:[
       
  3083             key := #fileLink
       
  3084         ] ifFalse:[
       
  3085             key := #file.
       
  3086             (f isReadable not) ifTrue:[
       
  3087                 key := #fileLocked
       
  3088             ] ifFalse:[
       
  3089                 (Image isImageFileSuffix:(f suffix)) ifTrue:[
       
  3090                     key := #imageFile
       
  3091                 ]
       
  3092             ].
       
  3093         ].
       
  3094     ].
       
  3095 
       
  3096     icons isNil ifTrue:[
       
  3097         icons := IdentityDictionary new
       
  3098     ].
       
  3099 
       
  3100     i := icons at:key ifAbsent:nil.
       
  3101     i isNil ifTrue:[
       
  3102         i := Icons at:key ifAbsent:nil.
       
  3103         i notNil ifTrue:[
       
  3104             i := i on:device.
       
  3105             icons at:key put:i.
       
  3106         ]
       
  3107     ].
       
  3108     ^ i
       
  3109 
       
  3110     "Modified: 18.4.1997 / 15:18:38 / cg"
       
  3111 !
       
  3112 
       
  3113 stopUpdateProcess
       
  3114     Processor removeTimedBlock:checkBlock.
       
  3115     listUpdateProcess notNil ifTrue:[
       
  3116         listUpdateProcess terminate.
       
  3117         listUpdateProcess := nil.
       
  3118     ].
       
  3119 
       
  3120     "Created: 19.4.1997 / 13:51:34 / cg"
       
  3121 !
       
  3122 
       
  3123 updateCurrentDirectory
       
  3124     "update listView with directory contents"
       
  3125 
       
  3126     "the code below may look somewhat complex -
       
  3127      it reads the directory first for the names,
       
  3128      then (in followup sweeps over the files) gets the
       
  3129      files type, info and icon in a forked subprocess. 
       
  3130      This makes the Filebrowsers list update faster, since the fileInfo 
       
  3131      (i.e. stat-calls) may take long - especially on NFS-mounted directories.
       
  3132      The file reading is done at lower priority, to let user continue
       
  3133      his work in other views. However, to be fair to other fileBrowser,
       
  3134      which may also read directories at low prio, give up the processor
       
  3135      after every entry. This shares the cpu among all fileBrowsers;
       
  3136      Therefore, browsers which read short directories will finish first.
       
  3137      ST/X users love this behavior ;-)
       
  3138     "
       
  3139 
       
  3140     self withReadCursorDo:[
       
  3141         |files matchPattern|
       
  3142 
       
  3143         self stopUpdateProcess.
       
  3144 
       
  3145         timeOfLastCheck := AbsoluteTime now.
       
  3146 
       
  3147         files := currentDirectory asOrderedCollection.
       
  3148 
       
  3149         "/ show files which are either directories
       
  3150         "/ or match the current pattern
       
  3151 
       
  3152         matchPattern := filterField contents.
       
  3153         (matchPattern notNil and:[
       
  3154          matchPattern isEmpty not and:[
       
  3155          matchPattern ~= '*']]) ifTrue:[
       
  3156              files := files select:[:aName | 
       
  3157                          ((currentDirectory typeOf:aName) == #directory)
       
  3158                          or:[matchPattern compoundMatch:aName]
       
  3159                       ].
       
  3160         ].
       
  3161 
       
  3162         files sort.
       
  3163 
       
  3164         files size == 0 ifTrue:[
       
  3165             self information:('directory ', currentDirectory pathName, ' vanished').
       
  3166             ^ self
       
  3167         ].
       
  3168         files := self withoutHiddenFiles:files.
       
  3169         fileList := files copy.
       
  3170 
       
  3171         "
       
  3172          this is a time consuming operation (especially, if reading an
       
  3173          NFS-mounted directory); therefore, start a low prio process,
       
  3174          which fills in the remaining fields in the fileList ...
       
  3175         "
       
  3176 
       
  3177         listUpdateProcess := [
       
  3178             |prevUid prevGid fileNameString nameString groupString 
       
  3179              modeString info line len list
       
  3180              anyImages passDone lineIndex aFileName
       
  3181              entry typ f p typeString done endIndex 
       
  3182              state stopAtEnd nextState img prevFirstLine prevLastLine
       
  3183              numVisible|
       
  3184 
       
  3185             tabSpec isNil ifTrue:[
       
  3186                 showLongList ifTrue:[
       
  3187                     self defineTabulatorsForLongList
       
  3188                 ] ifFalse:[
       
  3189                     self defineTabulatorsForShortList
       
  3190                 ].
       
  3191             ].
       
  3192 
       
  3193             "/
       
  3194             "/ first show all the names - this can be done fast ...
       
  3195             "/
       
  3196             list := files collect:[:fileName |
       
  3197                         |entry|
       
  3198 
       
  3199                         entry := MultiColListEntry new.
       
  3200                         entry tabulatorSpecification:tabSpec.
       
  3201                         entry colAt:1 put:nil.
       
  3202                         entry colAt:2 put:fileName.
       
  3203                     ].
       
  3204 
       
  3205             fileListView setList:list expandTabs:false.
       
  3206             passDone := Array new:list size withAll:0.
       
  3207 
       
  3208             "/
       
  3209             "/ then walk over the files, adding more info
       
  3210             "/ (since we have to stat each file, this may take a while longer)
       
  3211             "/ Visible items are always filled first.
       
  3212 
       
  3213             "/
       
  3214             "/ the state machine
       
  3215             "/
       
  3216             nextState := IdentityDictionary new.
       
  3217             showLongList ifTrue:[
       
  3218                 nextState add:(#visibleIcons -> #visibleAttributes).
       
  3219                 nextState add:(#visibleAttributes -> #visibleTypes).
       
  3220                 nextState add:(#visibleTypes -> #visibleImages).
       
  3221                 nextState add:(#visibleImages -> #nextPageIcons).
       
  3222 
       
  3223                 nextState add:(#nextPageIcons -> #nextPageAttributes).
       
  3224                 nextState add:(#nextPageAttributes -> #nextPageTypes).
       
  3225                 nextState add:(#nextPageTypes -> #nextPageImages).
       
  3226                 nextState add:(#nextPageImages -> #previousPageIcons).
       
  3227 
       
  3228                 nextState add:(#previousPageIcons -> #previousPageAttributes).
       
  3229                 nextState add:(#previousPageAttributes -> #previousPageTypes).
       
  3230                 nextState add:(#previousPageTypes -> #previousPageImages).
       
  3231                 nextState add:(#previousPageImages -> #remainingIcons).
       
  3232 
       
  3233                 nextState add:(#remainingIcons -> #remainingAttributes).
       
  3234                 nextState add:(#remainingAttributes -> #remainingTypes).
       
  3235                 nextState add:(#remainingTypes -> #remainingImages).
       
  3236                 nextState add:(#remainingImages -> nil).
       
  3237             ] ifFalse:[
       
  3238                 nextState add:(#visibleIcons -> #nextPageIcons).
       
  3239                 nextState add:(#nextPageIcons -> #previousPageIcons).
       
  3240                 nextState add:(#previousPageIcons -> #remainingIcons).
       
  3241                 nextState add:(#remainingIcons -> nil).
       
  3242             ].
       
  3243 
       
  3244             anyImages := false.
       
  3245 
       
  3246             lineIndex := prevFirstLine := fileListView firstLineShown.
       
  3247             endIndex := prevLastLine := fileListView lastLineShown.
       
  3248             endIndex := endIndex min:(files size).
       
  3249             state := #visibleIcons.
       
  3250 
       
  3251             done := false.
       
  3252             [done] whileFalse:[
       
  3253                 "/
       
  3254                 "/ if multiple FileBrowsers are reading, let others
       
  3255                 "/ make some progress too
       
  3256                 "/
       
  3257                 Processor yield.
       
  3258 
       
  3259                 "/
       
  3260                 "/ could be destroyed in the meanwhile ...
       
  3261                 "/
       
  3262                 realized ifFalse:[
       
  3263                     listUpdateProcess := nil.
       
  3264                     Processor activeProcess terminate
       
  3265                 ].
       
  3266 
       
  3267                 ((prevFirstLine ~~ fileListView firstLineShown)
       
  3268                 or:[prevLastLine ~~ fileListView lastLineShown]) ifTrue:[
       
  3269                     "/ start all over again
       
  3270                     lineIndex := prevFirstLine := fileListView firstLineShown.
       
  3271                     endIndex := prevLastLine := fileListView lastLineShown.
       
  3272                     endIndex := endIndex min:(files size).
       
  3273                     state := #visibleIcons.
       
  3274                 ].
       
  3275 
       
  3276                 (lineIndex between:1 and:(files size)) ifTrue:[
       
  3277 
       
  3278                     "/
       
  3279                     "/ expand the next entry ...
       
  3280                     "/
       
  3281                     aFileName := files at:lineIndex.
       
  3282                     entry := fileListView at:lineIndex.
       
  3283 
       
  3284                     (state endsWith:'Icons') ifTrue:[
       
  3285                         "/
       
  3286                         "/ pass 1 - icons
       
  3287                         "/
       
  3288                         (passDone at:lineIndex) < 1 ifTrue:[
       
  3289                             ((currentDirectory isDirectory:aFileName) and:[
       
  3290                             (aFileName ~= '..') and:[aFileName ~= '.']]) ifTrue:[
       
  3291                                 fileNameString := aFileName , ' ...'
       
  3292                             ] ifFalse:[
       
  3293                                 fileNameString := aFileName
       
  3294                             ].
       
  3295 
       
  3296                             showLongList ifTrue:[
       
  3297                                 len := fileNameString size.
       
  3298                                 (len > 20) ifTrue:[
       
  3299                                     fileNameString := (fileNameString contractTo:20)
       
  3300                                 ].
       
  3301                             ].
       
  3302 
       
  3303                             entry colAt:1 put:(self iconForFile:aFileName).
       
  3304                             entry colAt:2 put:fileNameString.
       
  3305 
       
  3306                             fileListView at:lineIndex put:entry.
       
  3307 
       
  3308                             anyImages ifFalse:[
       
  3309                                 (Image isImageFileSuffix:(aFileName asFilename suffix))
       
  3310                                 ifTrue:[
       
  3311                                     anyImages := true
       
  3312                                 ]
       
  3313                             ].
       
  3314                             passDone at:lineIndex put:1
       
  3315                         ]
       
  3316                     ].
       
  3317 
       
  3318                     (state endsWith:'Attributes') ifTrue:[
       
  3319                         "/
       
  3320                         "/ pass 2 - everything except fileType (which takes very long)
       
  3321                         "/
       
  3322                         (passDone at:lineIndex) < 2 ifTrue:[
       
  3323 
       
  3324                             info := currentDirectory infoOf:aFileName.
       
  3325                             info isNil ifTrue:[
       
  3326                                 "not accessable - usually a symlink,
       
  3327                                  to a nonexisting/nonreadable file
       
  3328                                 "
       
  3329                                 f := currentDirectory asFilename:aFileName.
       
  3330                                 f isSymbolicLink ifTrue:[
       
  3331                                     p := f linkInfo path.    
       
  3332                                     typeString := 'broken symbolic link to ' , p
       
  3333                                 ] ifFalse:[
       
  3334                                     typeString := 'unknwon (bad symbolic link ?)'
       
  3335                                 ].
       
  3336                                 entry colAt:7 put:typeString.
       
  3337                             ] ifFalse:[
       
  3338                                 typ := (info type).
       
  3339 
       
  3340                                 modeString := self getModeString:(info at:#mode)
       
  3341                                                             with:#( '' $r $w $x 
       
  3342                                                                     '  ' $r $w $x 
       
  3343                                                                     '  ' $r $w $x ).
       
  3344                                 entry colAt:3 put:modeString.
       
  3345 
       
  3346                                 ((info uid) ~~ prevUid) ifTrue:[
       
  3347                                     prevUid := (info uid).
       
  3348                                     nameString := OperatingSystem getUserNameFromID:prevUid.
       
  3349                                     nameString := nameString , (String new:(10 - nameString size))
       
  3350                                 ].
       
  3351                                 entry colAt:4 put:nameString withoutSpaces.
       
  3352 
       
  3353                                 ((info gid) ~~ prevGid) ifTrue:[
       
  3354                                     prevGid := (info gid).
       
  3355                                     groupString := OperatingSystem getGroupNameFromID:prevGid.
       
  3356                                     groupString := groupString , (String new:(10 - groupString size))
       
  3357                                 ].
       
  3358                                 entry colAt:5 put:groupString withoutSpaces.
       
  3359 
       
  3360                                 (typ == #regular) ifTrue:[
       
  3361                                     entry colAt:6 put:(self sizePrintString:(info size)).
       
  3362                                 ].
       
  3363 
       
  3364                                 f := currentDirectory asFilename:aFileName.
       
  3365                                 f isSymbolicLink ifTrue:[
       
  3366                                     p := f linkInfo path.    
       
  3367                                     typeString := 'symbolic link to ' , p
       
  3368                                 ] ifFalse:[
       
  3369                                     typeString := typ asString
       
  3370                                 ].
       
  3371                                 entry colAt:7 put:typeString
       
  3372                             ].
       
  3373                             fileListView at:lineIndex put:entry.
       
  3374                             passDone at:lineIndex put:2.
       
  3375                         ].
       
  3376                     ].
       
  3377 
       
  3378                     (state endsWith:'Types') ifTrue:[
       
  3379                         "/
       
  3380                         "/ pass 3: add fileType
       
  3381                         "/
       
  3382                         (passDone at:lineIndex) < 3 ifTrue:[
       
  3383                             info := currentDirectory infoOf:aFileName.
       
  3384                             info notNil ifTrue:[
       
  3385                                 f := currentDirectory asFilename:aFileName.
       
  3386                                 f isSymbolicLink ifFalse:[
       
  3387                                     (Image isImageFileSuffix:(f suffix)) ifFalse:[
       
  3388                                         typeString := f fileType.
       
  3389 
       
  3390                                         entry colAt:7 put:typeString.
       
  3391                                         fileListView at:lineIndex put:entry
       
  3392                                     ].
       
  3393                                 ].
       
  3394                             ].
       
  3395 
       
  3396                             passDone at:lineIndex put:3
       
  3397                         ].
       
  3398                     ].
       
  3399 
       
  3400                     (state endsWith:'Images') ifTrue:[
       
  3401                         "/
       
  3402                         "/ pass 4: read images
       
  3403                         "/
       
  3404                         (passDone at:lineIndex) < 4 ifTrue:[
       
  3405                             f := currentDirectory asFilename construct:aFileName.
       
  3406                             (Image isImageFileSuffix:(f suffix)) ifTrue:[
       
  3407                                 f isDirectory ifFalse:[
       
  3408                                     img := Image fromFile:(f pathName).
       
  3409                                     img notNil ifTrue:[
       
  3410                                         img := img magnifiedTo:16@16.
       
  3411                                         img := img on:self device.
       
  3412                                         entry colAt:7 put:img.
       
  3413                                         fileListView at:lineIndex put:entry
       
  3414                                     ]
       
  3415                                 ]
       
  3416                             ].
       
  3417                             passDone at:lineIndex put:4
       
  3418                         ].
       
  3419                     ].
       
  3420                 ].
       
  3421 
       
  3422                 "/
       
  3423                 "/ advance to the next line
       
  3424                 "/
       
  3425                 lineIndex := lineIndex + 1.
       
  3426                 lineIndex > endIndex ifTrue:[
       
  3427                     "/ finished this round ...
       
  3428                     "/ see what we are going for ...
       
  3429                     numVisible := (fileListView lastLineShown - fileListView firstLineShown + 1).
       
  3430 
       
  3431                     state := nextState at:state ifAbsent:nil.
       
  3432 
       
  3433                     state isNil ifTrue:[
       
  3434                         done := true
       
  3435                     ] ifFalse:[
       
  3436                         (state startsWith:'visible') ifTrue:[
       
  3437                             lineIndex := fileListView firstLineShown.
       
  3438                             endIndex := fileListView lastLineShown.
       
  3439                             endIndex := endIndex min:(files size).
       
  3440                         ] ifFalse:[
       
  3441                             (state startsWith:'nextPage') ifTrue:[
       
  3442                                 lineIndex := fileListView lastLineShown + 1.
       
  3443                                 endIndex := lineIndex + numVisible.
       
  3444                                 endIndex := endIndex min:(files size).
       
  3445                                 lineIndex := lineIndex min:(files size).
       
  3446                             ] ifFalse:[
       
  3447                                 (state startsWith:'previousPage') ifTrue:[
       
  3448                                     endIndex := fileListView firstLineShown - 1.
       
  3449                                     lineIndex := endIndex - numVisible.
       
  3450                                     lineIndex := lineIndex max:1.
       
  3451                                     endIndex := endIndex min:(files size).
       
  3452                                     endIndex := endIndex max:1.
       
  3453                                 ] ifFalse:[ 
       
  3454                                     "/ remaining
       
  3455                                     lineIndex := 1.
       
  3456                                     endIndex := files size.
       
  3457                                 ]
       
  3458                             ]
       
  3459                         ]
       
  3460                     ]
       
  3461                 ]
       
  3462             ].
       
  3463 
       
  3464             listUpdateProcess := nil.
       
  3465 
       
  3466         ] forkAt:(Processor activePriority - 1).
       
  3467 
       
  3468         "
       
  3469          install a new check after some time
       
  3470         "
       
  3471         Processor addTimedBlock:checkBlock afterSeconds:checkDelta
       
  3472     ]
       
  3473 
       
  3474     "Modified: 21.9.1995 / 11:40:23 / claus"
       
  3475     "Modified: 21.4.1997 / 15:01:27 / cg"
       
  3476 ! !
       
  3477 
  3448 !FileBrowser methodsFor:'queries'!
  3478 !FileBrowser methodsFor:'queries'!
  3449 
  3479 
  3450 path
  3480 path
  3451     "return my currentDirectories pathName;
  3481     "return my currentDirectories pathName;
  3452      sent from the pathField label to aquire pathname when I changed directory"
  3482      sent from the pathField label to aquire pathname when I changed directory"
  3455 ! !
  3485 ! !
  3456 
  3486 
  3457 !FileBrowser class methodsFor:'documentation'!
  3487 !FileBrowser class methodsFor:'documentation'!
  3458 
  3488 
  3459 version
  3489 version
  3460     ^ '$Header: /cvs/stx/stx/libtool/Attic/FBrowser.st,v 1.151 1997-04-21 13:03:56 cg Exp $'
  3490     ^ '$Header: /cvs/stx/stx/libtool/Attic/FBrowser.st,v 1.152 1997-04-23 11:30:25 cg Exp $'
  3461 ! !
  3491 ! !
  3462 FileBrowser initialize!
  3492 FileBrowser initialize!