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. |
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" |