PhoneticStringUtilities.st
changeset 2213 d465fa29df0e
parent 2211 42fe8fe39e9c
child 2215 c1f072a78366
equal deleted inserted replaced
2212:e83d602a2aa7 2213:d465fa29df0e
   146     schulz      S242    24200000    SKLS        SHULS   ZULZ        S4800000    484000  CULC        85
   146     schulz      S242    24200000    SKLS        SHULS   ZULZ        S4800000    484000  CULC        85
   147     becker      B260    12600000    BKR         BEKA    BEKA        B2000000    759000  BCR         147
   147     becker      B260    12600000    BKR         BEKA    BEKA        B2000000    759000  BCR         147
   148     hoffmann    H155    15500000    HFMN        HOFMAN  UFNAN       $7550000    576600  OVMAN       036
   148     hoffmann    H155    15500000    HFMN        HOFMAN  UFNAN       $7550000    576600  OVMAN       036
   149     schäfer     S216    21600000    SKFR        SHEFA   ZEFA        S7000000    479000  CVR         837
   149     schäfer     S216    21600000    SKFR        SHEFA   ZEFA        S7000000    479000  CVR         837
   150 "
   150 "
   151 ! !
       
   152 
       
   153 !PhoneticStringUtilities class methodsFor:'classification'!
       
   154 
       
   155 isSlavoGermanic:aString
       
   156     ^ #('w' 'k' 'cz' 'witz') contains:[:sub | aString includesString:sub]
       
   157 
       
   158     "
       
   159      self isSlavoGermanic:'walter'
       
   160     "
       
   161 ! !
   151 ! !
   162 
   152 
   163 !PhoneticStringUtilities class methodsFor:'phonetic codes'!
   153 !PhoneticStringUtilities class methodsFor:'phonetic codes'!
   164 
   154 
   165 koelnerPhoneticCodeOf:aString
   155 koelnerPhoneticCodeOf:aString
  1427 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 
  1417 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 
  1428 USE OR OTHER DEALINGS IN THE SOFTWARE.'
  1418 USE OR OTHER DEALINGS IN THE SOFTWARE.'
  1429 "
  1419 "
  1430 ! !
  1420 ! !
  1431 
  1421 
       
  1422 !PhoneticStringUtilities::DoubleMetaphoneStringComparator class methodsFor:'classification'!
       
  1423 
       
  1424 isSlavoGermanic:aString
       
  1425     ^ #('w' 'k' 'cz' 'witz') contains:[:sub | aString includesString:sub]
       
  1426 
       
  1427     "
       
  1428      self isSlavoGermanic:'walter'
       
  1429     "
       
  1430 ! !
       
  1431 
  1432 !PhoneticStringUtilities::DoubleMetaphoneStringComparator class methodsFor:'documentation'!
  1432 !PhoneticStringUtilities::DoubleMetaphoneStringComparator class methodsFor:'documentation'!
  1433 
  1433 
  1434 documentaion
  1434 documentaion
  1435 "
  1435 "
  1436 The Double Metaphone algorithm:
  1436 The Double Metaphone algorithm:
  1606 				addSecondaryTranslation: 'A'.
  1606 				addSecondaryTranslation: 'A'.
  1607 			self incrementStartIndex ]
  1607 			self incrementStartIndex ]
  1608 !
  1608 !
  1609 
  1609 
  1610 processB
  1610 processB
  1611 	self
  1611         self
  1612 		addPrimaryTranslation: 'P';
  1612                 addPrimaryTranslation: 'P';
  1613 		addSecondaryTranslation: 'P'.
  1613                 addSecondaryTranslation: 'P'.
  1614 	(self keyAt: (self currentIndex + 1)) = $B
  1614         (self keyAt: (currentIndex + 1)) = $B
  1615 		ifTrue: [ self incrementSkipCount ].
  1615                 ifTrue: [ self incrementSkipCount ].
  1616 !
  1616 !
  1617 
  1617 
  1618 processC
  1618 processC
  1619 	"i"
  1619         "i"
  1620 	((((currentIndex >= 3
  1620         ((((currentIndex >= 3
  1621 		and: [ (self keyAt: self currentIndex-2) isVowel not ])
  1621                 and: [ (self keyAt: currentIndex-2) isVowel not ])
  1622 		and: [ (self keyMidString: 3 from: self currentIndex-1) = 'ACH' ])
  1622                 and: [ (self keyMidString: 3 from: currentIndex-1) = 'ACH' ])
  1623 		and: [ (self keyAt: self currentIndex+2) ~= $I ])
  1623                 and: [ (self keyAt: currentIndex+2) ~= $I ])
  1624 		and: [ ((self keyAt: self currentIndex+2) ~= $E)
  1624                 and: [ ((self keyAt: currentIndex+2) ~= $E)
  1625 				or: [ (self keyMidString: 6 from: self currentIndex-2) ~= 'BACHER'
  1625                                 or: [ (self keyMidString: 6 from: currentIndex-2) ~= 'BACHER'
  1626 						and: [ (self keyMidString: 6 from: self currentIndex-2) ~= 'MACHER' ] ] ])
  1626                                                 and: [ (self keyMidString: 6 from: currentIndex-2) ~= 'MACHER' ] ] ])
  1627 			ifTrue:
  1627                         ifTrue:
  1628 				[ self addPrimaryTranslation: 'K'.
  1628                                 [ self addPrimaryTranslation: 'K'.
  1629 				self addSecondaryTranslation: 'K'.
  1629                                 self addSecondaryTranslation: 'K'.
  1630 				self incrementSkipCount: 2.
  1630                                 self incrementSkipCount: 2.
  1631 				^self ].
  1631                                 ^self ].
  1632 
  1632 
  1633 	"ii"
  1633         "ii"
  1634 	(self inputKey beginsWith: 'CAESAR')
  1634         (self inputKey beginsWith: 'CAESAR')
  1635 		ifTrue:
  1635                 ifTrue:
  1636 			[ self addPrimaryTranslation: 'S'.
  1636                         [ self addPrimaryTranslation: 'S'.
  1637 			self addSecondaryTranslation: 'S'.
  1637                         self addSecondaryTranslation: 'S'.
  1638 			self incrementSkipCount: 1.
  1638                         self incrementSkipCount: 1.
  1639 			^self ].
  1639                         ^self ].
  1640 
  1640 
  1641 	"iii"
  1641         "iii"
  1642 	(self keyMidString: 4 from: self currentIndex) = 'CHIA'
  1642         (self keyMidString: 4 from: currentIndex) = 'CHIA'
  1643 		ifTrue:
  1643                 ifTrue:
  1644 			[ self addPrimaryTranslation: 'K'.
  1644                         [ self addPrimaryTranslation: 'K'.
  1645 			self addSecondaryTranslation: 'K'.
  1645                         self addSecondaryTranslation: 'K'.
  1646 			self incrementSkipCount: 1.
  1646                         self incrementSkipCount: 1.
  1647 			^self ].
  1647                         ^self ].
  1648 
  1648 
  1649 	"iv"
  1649         "iv"
  1650 	(self keyMidString: 2 from: self currentIndex) = 'CH'
  1650         (self keyMidString: 2 from: currentIndex) = 'CH'
  1651 		ifTrue:
  1651                 ifTrue:
  1652 			[ (self currentIndex > 1		"a"
  1652                         [ (currentIndex > 1                "a"
  1653 					and: [ (self keyMidString: 4 from: self currentIndex) = 'CHAE' ])
  1653                                         and: [ (self keyMidString: 4 from: currentIndex) = 'CHAE' ])
  1654 				ifTrue: [ self
  1654                                 ifTrue: [ self
  1655 						addPrimaryTranslation: 'K';
  1655                                                 addPrimaryTranslation: 'K';
  1656 						addSecondaryTranslation: 'X';
  1656                                                 addSecondaryTranslation: 'X';
  1657 						incrementSkipCount: 1.
  1657                                                 incrementSkipCount: 1.
  1658 						^self ].
  1658                                                 ^self ].
  1659 
  1659 
  1660 			(self currentIndex = 1		"b"
  1660                         (currentIndex = 1          "b"
  1661 					and: [ (self inputKey size > 5 and: [(self inputKey copyFrom: 1 to: 6) = 'CHARAC'
  1661                                         and: [ (self inputKey size > 5 and: [(self inputKey copyFrom: 1 to: 6) = 'CHARAC'
  1662 							or: [ (self inputKey copyFrom: 1 to: 6) = 'CHARIS' ]] )
  1662                                                         or: [ (self inputKey copyFrom: 1 to: 6) = 'CHARIS' ]] )
  1663 						or: [self inputKey size > 4 and: [ ((((self inputKey copyFrom: 1 to: 4) = 'CHOR'
  1663                                                 or: [self inputKey size > 4 and: [ ((((self inputKey copyFrom: 1 to: 4) = 'CHOR'
  1664 							or: [ (self inputKey copyFrom: 1 to: 4) = 'CHYM' ])
  1664                                                         or: [ (self inputKey copyFrom: 1 to: 4) = 'CHYM' ])
  1665 							or: [ (self inputKey copyFrom: 1 to: 4) = 'CHIA' ])
  1665                                                         or: [ (self inputKey copyFrom: 1 to: 4) = 'CHIA' ])
  1666 							or: [ (self inputKey copyFrom: 1 to: 4) = 'CHEM' ])
  1666                                                         or: [ (self inputKey copyFrom: 1 to: 4) = 'CHEM' ])
  1667 							and: [ (self inputKey copyFrom: 1 to: 4) ~= 'CHORE' ] ] ] ])
  1667                                                         and: [ (self inputKey copyFrom: 1 to: 4) ~= 'CHORE' ] ] ] ])
  1668 				ifTrue: [ self
  1668                                 ifTrue: [ self
  1669 						addPrimaryTranslation: 'K';
  1669                                                 addPrimaryTranslation: 'K';
  1670 						addSecondaryTranslation: 'K';
  1670                                                 addSecondaryTranslation: 'K';
  1671 						incrementSkipCount: 1.
  1671                                                 incrementSkipCount: 1.
  1672 						^self ].
  1672                                                 ^self ].
  1673 
  1673 
  1674 			(((((#('VAN ' 'VON ') includes: (self inputKey copyFrom: 1 to: 4))		"c"
  1674                         (((((#('VAN ' 'VON ') includes: (self inputKey copyFrom: 1 to: 4))              "c"
  1675 					or: [ (self inputKey copyFrom: 1 to: 3) = 'SCH' ])
  1675                                         or: [ (self inputKey copyFrom: 1 to: 3) = 'SCH' ])
  1676 					or: [ #('ORCHES' 'ARCHIT' 'ORCHID')
  1676                                         or: [ #('ORCHES' 'ARCHIT' 'ORCHID')
  1677 							includes: (self keyMidString: 6 from: self currentIndex-2) ])
  1677                                                         includes: (self keyMidString: 6 from: currentIndex-2) ])
  1678 					or: [ #($T $S) includes: (self keyAt: self currentIndex+2) ])
  1678                                         or: [ #($T $S) includes: (self keyAt: currentIndex+2) ])
  1679 					or: [ ((self currentIndex = 1)
  1679                                         or: [ ((currentIndex = 1)
  1680 							or: [ #($A $O $U $E) includes: (self keyAt: self currentIndex-1) ])
  1680                                                         or: [ #($A $O $U $E) includes: (self keyAt: currentIndex-1) ])
  1681 						and: [ #($L $R $N $M $B $H $F $V $W $ ) includes: (self keyAt: self currentIndex+2) ] ] )
  1681                                                 and: [ #($L $R $N $M $B $H $F $V $W $ ) includes: (self keyAt: currentIndex+2) ] ] )
  1682 				ifTrue:
  1682                                 ifTrue:
  1683 					[ self
  1683                                         [ self
  1684 						addPrimaryTranslation: 'K';
  1684                                                 addPrimaryTranslation: 'K';
  1685 						addSecondaryTranslation: 'K';
  1685                                                 addSecondaryTranslation: 'K';
  1686 						incrementSkipCount: 1.
  1686                                                 incrementSkipCount: 1.
  1687 						^self ]
  1687                                                 ^self ]
  1688 				ifFalse:
  1688                                 ifFalse:
  1689 					[ self currentIndex > 1
  1689                                         [ currentIndex > 1
  1690 						ifTrue:
  1690                                                 ifTrue:
  1691 							[ (self inputKey copyFrom: 1 to: 2) = 'MC'
  1691                                                         [ (self inputKey copyFrom: 1 to: 2) = 'MC'
  1692 								ifTrue:
  1692                                                                 ifTrue:
  1693 										[ self
  1693                                                                                 [ self
  1694 												addPrimaryTranslation: 'K';
  1694                                                                                                 addPrimaryTranslation: 'K';
  1695 												addSecondaryTranslation: 'K' ]
  1695                                                                                                 addSecondaryTranslation: 'K' ]
  1696 								ifFalse:
  1696                                                                 ifFalse:
  1697 										[ self
  1697                                                                                 [ self
  1698 												addPrimaryTranslation: 'X';
  1698                                                                                                 addPrimaryTranslation: 'X';
  1699 												addSecondaryTranslation: 'K' ] ]
  1699                                                                                                 addSecondaryTranslation: 'K' ] ]
  1700 						ifFalse:
  1700                                                 ifFalse:
  1701 							[ self
  1701                                                         [ self
  1702 								addPrimaryTranslation: 'X';
  1702                                                                 addPrimaryTranslation: 'X';
  1703 								addSecondaryTranslation: 'X' ].
  1703                                                                 addSecondaryTranslation: 'X' ].
  1704 					self incrementSkipCount: 1.
  1704                                         self incrementSkipCount: 1.
  1705 					^self ] ].
  1705                                         ^self ] ].
  1706 
  1706 
  1707 	"v"
  1707         "v"
  1708 	(self keyAt: self currentIndex+1) = $Z
  1708         (self keyAt: currentIndex+1) = $Z
  1709 		ifTrue:
  1709                 ifTrue:
  1710 			[ self
  1710                         [ self
  1711 				addPrimaryTranslation: 'S';
  1711                                 addPrimaryTranslation: 'S';
  1712 				addSecondaryTranslation: 'X';
  1712                                 addSecondaryTranslation: 'X';
  1713 				incrementSkipCount: 1.
  1713                                 incrementSkipCount: 1.
  1714 				^self ].
  1714                                 ^self ].
  1715 
  1715 
  1716 	"vi"
  1716         "vi"
  1717 	(self keyMidString: 3 from: self currentIndex+1) = 'CIA'
  1717         (self keyMidString: 3 from: currentIndex+1) = 'CIA'
  1718 		ifTrue:
  1718                 ifTrue:
  1719 			[ self
  1719                         [ self
  1720 				addPrimaryTranslation: 'X';
  1720                                 addPrimaryTranslation: 'X';
  1721 				addSecondaryTranslation: 'X';
  1721                                 addSecondaryTranslation: 'X';
  1722 				incrementSkipCount: 2.
  1722                                 incrementSkipCount: 2.
  1723 				^self ].
  1723                                 ^self ].
  1724 
  1724 
  1725 	"vii"
  1725         "vii"
  1726 	((self keyAt: self currentIndex+1) = $C
  1726         ((self keyAt: currentIndex+1) = $C
  1727 			and: [ ((currentIndex = 2)
  1727                         and: [ ((currentIndex = 2)
  1728 				and: [ (self keyAt: 1) = $M ]) not ])
  1728                                 and: [ (self keyAt: 1) = $M ]) not ])
  1729 		ifTrue:
  1729                 ifTrue:
  1730 			[ ((#($I $E $H) includes: (self keyAt: self currentIndex+2))
  1730                         [ ((#($I $E $H) includes: (self keyAt: currentIndex+2))
  1731 					and: [ (self keyMidString: 2 from: self currentIndex+2) ~= 'HU' ])
  1731                                         and: [ (self keyMidString: 2 from: currentIndex+2) ~= 'HU' ])
  1732 				ifTrue:
  1732                                 ifTrue:
  1733 					[ ((self currentIndex = 2 and: [ (self keyAt: 1) = $A ])
  1733                                         [ ((currentIndex = 2 and: [ (self keyAt: 1) = $A ])
  1734 							or: [ #('UCCEE' 'UCCES') includes: (self keyMidString: 5 from: self currentIndex-1)])
  1734                                                         or: [ #('UCCEE' 'UCCES') includes: (self keyMidString: 5 from: currentIndex-1)])
  1735 						ifTrue:
  1735                                                 ifTrue:
  1736 							[self
  1736                                                         [self
  1737 								addPrimaryTranslation: 'KS';
  1737                                                                 addPrimaryTranslation: 'KS';
  1738 								addSecondaryTranslation: 'KS';
  1738                                                                 addSecondaryTranslation: 'KS';
  1739 								incrementSkipCount: 2.
  1739                                                                 incrementSkipCount: 2.
  1740 								^self ]
  1740                                                                 ^self ]
  1741 						ifFalse:
  1741                                                 ifFalse:
  1742 							[self
  1742                                                         [self
  1743 								addPrimaryTranslation: 'X';
  1743                                                                 addPrimaryTranslation: 'X';
  1744 								addSecondaryTranslation: 'X';
  1744                                                                 addSecondaryTranslation: 'X';
  1745 								incrementSkipCount: 2.
  1745                                                                 incrementSkipCount: 2.
  1746 								^self ] ]
  1746                                                                 ^self ] ]
  1747 				ifFalse:
  1747                                 ifFalse:
  1748 					[ self
  1748                                         [ self
  1749 						addPrimaryTranslation: 'K';
  1749                                                 addPrimaryTranslation: 'K';
  1750 						addSecondaryTranslation: 'K';
  1750                                                 addSecondaryTranslation: 'K';
  1751 						incrementSkipCount: 2.
  1751                                                 incrementSkipCount: 2.
  1752 						^self ] ].
  1752                                                 ^self ] ].
  1753 
  1753 
  1754 	"viii"
  1754         "viii"
  1755 	(#($K $G $Q) includes: (self keyAt: self currentIndex+1))
  1755         (#($K $G $Q) includes: (self keyAt: currentIndex+1))
  1756 		ifTrue:
  1756                 ifTrue:
  1757 			[ self
  1757                         [ self
  1758 				addPrimaryTranslation: 'K';
  1758                                 addPrimaryTranslation: 'K';
  1759 				addSecondaryTranslation: 'K';
  1759                                 addSecondaryTranslation: 'K';
  1760 				incrementSkipCount: 1.
  1760                                 incrementSkipCount: 1.
  1761 				^self ].
  1761                                 ^self ].
  1762 
  1762 
  1763 	"ix"
  1763         "ix"
  1764 	(#($I $E $Y) includes: (self keyAt: self currentIndex+1))
  1764         (#($I $E $Y) includes: (self keyAt: currentIndex+1))
  1765 		ifTrue:
  1765                 ifTrue:
  1766 			[ (#('CIO' 'CIE' 'CIA') includes: (self keyMidString: 3 from: self currentIndex))
  1766                         [ (#('CIO' 'CIE' 'CIA') includes: (self keyMidString: 3 from: currentIndex))
  1767 				ifTrue:
  1767                                 ifTrue:
  1768 					[self
  1768                                         [self
  1769 						addPrimaryTranslation: 'S';
  1769                                                 addPrimaryTranslation: 'S';
  1770 						addSecondaryTranslation: 'X' ]
  1770                                                 addSecondaryTranslation: 'X' ]
  1771 				ifFalse:
  1771                                 ifFalse:
  1772 					[self
  1772                                         [self
  1773 						addPrimaryTranslation: 'S';
  1773                                                 addPrimaryTranslation: 'S';
  1774 						addSecondaryTranslation: 'S'].
  1774                                                 addSecondaryTranslation: 'S'].
  1775 			self incrementSkipCount: 1.
  1775                         self incrementSkipCount: 1.
  1776 			^self ].
  1776                         ^self ].
  1777 
  1777 
  1778 	"x"
  1778         "x"
  1779 	self
  1779         self
  1780 		addPrimaryTranslation: 'K';
  1780                 addPrimaryTranslation: 'K';
  1781 		addSecondaryTranslation: 'K'.
  1781                 addSecondaryTranslation: 'K'.
  1782 
  1782 
  1783 	"xi"
  1783         "xi"
  1784 	(#(' C' ' Q' ' G') includes: (self keyMidString: 2 from: self currentIndex+1))
  1784         (#(' C' ' Q' ' G') includes: (self keyMidString: 2 from: currentIndex+1))
  1785 		ifTrue:
  1785                 ifTrue:
  1786 			[ self incrementSkipCount: 2 ]
  1786                         [ self incrementSkipCount: 2 ]
  1787 		ifFalse:
  1787                 ifFalse:
  1788 			[ ((#($C $K $Q) includes: (self keyAt: self currentIndex+1))
  1788                         [ ((#($C $K $Q) includes: (self keyAt: currentIndex+1))
  1789 					and: [ (#('CE' 'CI') includes: (self keyMidString: 2 from: self currentIndex+1)) not ])
  1789                                         and: [ (#('CE' 'CI') includes: (self keyMidString: 2 from: currentIndex+1)) not ])
  1790 				ifTrue: [ self incrementSkipCount: 1] ]
  1790                                 ifTrue: [ self incrementSkipCount: 1] ]
  1791 !
  1791 !
  1792 
  1792 
  1793 processCedille 
  1793 processCedille 
  1794 	self
  1794 	self
  1795 		addPrimaryTranslation: 'S';
  1795 		addPrimaryTranslation: 'S';
  1796 		addSecondaryTranslation: 'S'
  1796 		addSecondaryTranslation: 'S'
  1797 !
  1797 !
  1798 
  1798 
  1799 processD
  1799 processD
  1800 	"i"
  1800         "i"
  1801 	(self keyAt: self currentIndex+1) = $G
  1801         (self keyAt: currentIndex+1) = $G
  1802 		ifTrue:
  1802                 ifTrue:
  1803 			[ (#($I $E $Y) includes: (self keyAt: self currentIndex+2))
  1803                         [ (#($I $E $Y) includes: (self keyAt: currentIndex+2))
  1804 				ifTrue:
  1804                                 ifTrue:
  1805 					[ self
  1805                                         [ self
  1806 						addPrimaryTranslation: 'J';
  1806                                                 addPrimaryTranslation: 'J';
  1807 						addSecondaryTranslation: 'J';
  1807                                                 addSecondaryTranslation: 'J';
  1808 						incrementSkipCount: 2.
  1808                                                 incrementSkipCount: 2.
  1809 					^self ]
  1809                                         ^self ]
  1810 				ifFalse:
  1810                                 ifFalse:
  1811 					[ self
  1811                                         [ self
  1812 						addPrimaryTranslation: 'TK';
  1812                                                 addPrimaryTranslation: 'TK';
  1813 						addSecondaryTranslation: 'TK';
  1813                                                 addSecondaryTranslation: 'TK';
  1814 						incrementSkipCount: 1.
  1814                                                 incrementSkipCount: 1.
  1815 					^self ] ].
  1815                                         ^self ] ].
  1816 
  1816 
  1817 	"ii"
  1817         "ii"
  1818 	(#($T $D) includes: (self keyAt: self currentIndex+1))
  1818         (#($T $D) includes: (self keyAt: currentIndex+1))
  1819 		ifTrue:
  1819                 ifTrue:
  1820 			[ self
  1820                         [ self
  1821 				addPrimaryTranslation: 'T';
  1821                                 addPrimaryTranslation: 'T';
  1822 				addSecondaryTranslation: 'T';
  1822                                 addSecondaryTranslation: 'T';
  1823 				incrementSkipCount: 1.
  1823                                 incrementSkipCount: 1.
  1824 			^self ].
  1824                         ^self ].
  1825 
  1825 
  1826 	"iii"
  1826         "iii"
  1827 	self
  1827         self
  1828 		addPrimaryTranslation: 'T';
  1828                 addPrimaryTranslation: 'T';
  1829 		addSecondaryTranslation: 'T'
  1829                 addSecondaryTranslation: 'T'
  1830 !
  1830 !
  1831 
  1831 
  1832 processF
  1832 processF
  1833 	self
  1833 	self
  1834 		addPrimaryTranslation: 'F';
  1834 		addPrimaryTranslation: 'F';
  1841         "http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  1841         "http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  1842         case 'G':
  1842         case 'G':
  1843                 if(GetAt(current + 1) == 'H')
  1843                 if(GetAt(current + 1) == 'H')
  1844           {"
  1844           {"
  1845         | word |
  1845         | word |
  1846         (self keyAt: self currentIndex + 1) = $H
  1846         (self keyAt: currentIndex + 1) = $H
  1847         ifTrue: [
  1847         ifTrue: [
  1848                 "if((current > 0) AND !!IsVowel(current - 1))"
  1848                 "if((current > 0) AND !!IsVowel(current - 1))"
  1849 
  1849 
  1850                 (self currentIndex > 1 and: [(self keyAt: self currentIndex - 1) isVowel not])
  1850                 (currentIndex > 1 and: [(self keyAt: currentIndex - 1) isVowel not])
  1851                 ifTrue: [
  1851                 ifTrue: [
  1852               " {
  1852               " {
  1853                    MetaphAdd(K);
  1853                    MetaphAdd(K);
  1854                    current += 2;
  1854                    current += 2;
  1855                    break;
  1855                    break;
  1871                { "
  1871                { "
  1872                         currentIndex = 1 
  1872                         currentIndex = 1 
  1873                         ifTrue: [
  1873                         ifTrue: [
  1874                                 "if(GetAt(current + 2) == 'I')"
  1874                                 "if(GetAt(current + 2) == 'I')"
  1875 
  1875 
  1876                                 (self keyAt: self currentIndex + 2) = $I
  1876                                 (self keyAt: currentIndex + 2) = $I
  1877                                 ifTrue: [
  1877                                 ifTrue: [
  1878                                         "MetaphAdd(J);"
  1878                                         "MetaphAdd(J);"
  1879                                         self addPrimaryTranslation: 'J';
  1879                                         self addPrimaryTranslation: 'J';
  1880                                         addSecondaryTranslation: 'J'.
  1880                                         addSecondaryTranslation: 'J'.
  1881                                 ] ifFalse: [
  1881                                 ] ifFalse: [
  1894                 //e.g., 'bough'
  1894                 //e.g., 'bough'
  1895                 OR ((current > 2) AND StringAt((current - 3), 1, B, H, D, ) )
  1895                 OR ((current > 2) AND StringAt((current - 3), 1, B, H, D, ) )
  1896                 //e.g., 'broughton'
  1896                 //e.g., 'broughton'
  1897                 OR ((current > 3) AND StringAt((current - 4), 1, B, H, ) ) )
  1897                 OR ((current > 3) AND StringAt((current - 4), 1, B, H, ) ) )
  1898          "
  1898          "
  1899                 (((currentIndex > 2 and: [#($B $H $D) includes: (self keyAt: self currentIndex - 2)]) 
  1899                 (((currentIndex > 2 and: [#($B $H $D) includes: (self keyAt: currentIndex - 2)]) 
  1900                 or: [currentIndex > 3 and: [#($B $H $D) includes: (self keyAt: self currentIndex - 3)]])  
  1900                 or: [currentIndex > 3 and: [#($B $H $D) includes: (self keyAt: currentIndex - 3)]])  
  1901                 or: [currentIndex > 4 and: [#($B $H) includes: (self keyAt: self currentIndex - 4)]])   
  1901                 or: [currentIndex > 4 and: [#($B $H) includes: (self keyAt: currentIndex - 4)]])   
  1902                 ifTrue: [                         
  1902                 ifTrue: [                         
  1903                         "current += 2;
  1903                         "current += 2;
  1904                         break;"
  1904                         break;"
  1905                         ^self incrementSkipCount: 1 
  1905                         ^self incrementSkipCount: 1 
  1906                 ] ifFalse: [
  1906                 ] ifFalse: [
  1907                         " //e.g., 'laugh', 'McLaughlin', 'cough', 'gough', 'rough', 'tough'
  1907                         " //e.g., 'laugh', 'McLaughlin', 'cough', 'gough', 'rough', 'tough'
  1908                if((current > 2) 
  1908                if((current > 2) 
  1909                AND (GetAt(current - 1) == 'U') 
  1909                AND (GetAt(current - 1) == 'U') 
  1910                AND StringAt((current - 3), 1, C, G, L, R, T, ) )"
  1910                AND StringAt((current - 3), 1, C, G, L, R, T, ) )"
  1911                         (currentIndex > 3 and: [
  1911                         (currentIndex > 3 and: [
  1912                                 ((self keyAt: self currentIndex - 1) = $U) and: [
  1912                                 ((self keyAt: currentIndex - 1) = $U) and: [
  1913                                         #($C $G $L $R $T) includes: (self keyAt: self currentIndex - 3)
  1913                                         #($C $G $L $R $T) includes: (self keyAt: currentIndex - 3)
  1914                                 ]
  1914                                 ]
  1915                         ]) ifTrue: [
  1915                         ]) ifTrue: [
  1916                                 "MetaphAdd(F);"
  1916                                 "MetaphAdd(F);"
  1917                                 self addPrimaryTranslation: 'F';
  1917                                 self addPrimaryTranslation: 'F';
  1918                                 addSecondaryTranslation: 'F'.
  1918                                 addSecondaryTranslation: 'F'.
  1919                         ] ifFalse: [
  1919                         ] ifFalse: [
  1920                                 " if((current > 0) AND GetAt(current - 1) !!= 'I')
  1920                                 " if((current > 0) AND GetAt(current - 1) !!= 'I')
  1921                     MetaphAdd(K);"
  1921                     MetaphAdd(K);"
  1922                                 (currentIndex > 1 and: [(self keyAt: self currentIndex - 1) ~= $I])
  1922                                 (currentIndex > 1 and: [(self keyAt: currentIndex - 1) ~= $I])
  1923                                 ifTrue: [
  1923                                 ifTrue: [
  1924                                         self addPrimaryTranslation: 'K';
  1924                                         self addPrimaryTranslation: 'K';
  1925                                         addSecondaryTranslation: 'K'.
  1925                                         addSecondaryTranslation: 'K'.
  1926                                 ].
  1926                                 ].
  1927                         ].
  1927                         ].
  1928                         ^self incrementSkipCount: 1 
  1928                         ^self incrementSkipCount: 1 
  1929                 ].
  1929                 ].
  1930         ].
  1930         ].
  1931                 "if(GetAt(current + 1) == 'N')"
  1931                 "if(GetAt(current + 1) == 'N')"
  1932           (self keyAt: self currentIndex + 1) = $N
  1932           (self keyAt: currentIndex + 1) = $N
  1933                 ifTrue: [
  1933                 ifTrue: [
  1934                         "if((current == 1) AND IsVowel(0) AND !!SlavoGermanic())"
  1934                         "if((current == 1) AND IsVowel(0) AND !!SlavoGermanic())"
  1935                         (currentIndex = 2 and: [(self inputKey at: 1) isVowel and: [(self isSlavoGermanic: self inputKey) not]])
  1935                         (currentIndex = 2 and: [(self inputKey at: 1) isVowel and: [(self isSlavoGermanic: self inputKey) not]])
  1936                ifTrue: [
  1936                ifTrue: [
  1937                                 "MetaphAdd(KN, N);"
  1937                                 "MetaphAdd(KN, N);"
  1940                         ] ifFalse: [
  1940                         ] ifFalse: [
  1941                                 " //not e.g. 'cagney'
  1941                                 " //not e.g. 'cagney'
  1942                                 if(!!StringAt((current + 2), 2, EY, ) 
  1942                                 if(!!StringAt((current + 2), 2, EY, ) 
  1943                                 AND (GetAt(current + 1) !!= 'Y') 
  1943                                 AND (GetAt(current + 1) !!= 'Y') 
  1944                                 AND !!SlavoGermanic())"
  1944                                 AND !!SlavoGermanic())"
  1945                                 ((self inputKey size >= (self currentIndex + 2)) and: [
  1945                                 ((self inputKey size >= (currentIndex + 2)) and: [
  1946                                         (self inputKey copyFrom: self currentIndex + 2 to: (self currentIndex + 4 min: self inputKey size)) ~= 'EY' and: [
  1946                                         (self inputKey copyFrom: currentIndex + 2 to: (currentIndex + 4 min: self inputKey size)) ~= 'EY' and: [
  1947                                                 (self keyAt: self currentIndex + 1) ~= $Y and: [
  1947                                                 (self keyAt: currentIndex + 1) ~= $Y and: [
  1948                                                         (self isSlavoGermanic: self inputKey) not
  1948                                                         (self isSlavoGermanic: self inputKey) not
  1949                                                 ]
  1949                                                 ]
  1950                                         ]
  1950                                         ]
  1951                                 ]) ifTrue: [
  1951                                 ]) ifTrue: [
  1952                                         self addPrimaryTranslation: 'N';
  1952                                         self addPrimaryTranslation: 'N';
  1958                         ].
  1958                         ].
  1959                         ^self incrementSkipCount: 1 
  1959                         ^self incrementSkipCount: 1 
  1960                 ].
  1960                 ].
  1961                 " //'tagliaro'
  1961                 " //'tagliaro'
  1962                 if(StringAt((current + 1), 2, LI, ) AND !!SlavoGermanic())"
  1962                 if(StringAt((current + 1), 2, LI, ) AND !!SlavoGermanic())"
  1963                 ((self inputKey size >= (self currentIndex + 3)) and: [
  1963                 ((self inputKey size >= (currentIndex + 3)) and: [
  1964                         (self inputKey copyFrom: self currentIndex + 1 to: self currentIndex + 2) = 'LI' and: [
  1964                         (self inputKey copyFrom: currentIndex + 1 to: currentIndex + 2) = 'LI' and: [
  1965                                 (self isSlavoGermanic: self inputKey) not]])
  1965                                 (self isSlavoGermanic: self inputKey) not]])
  1966                 ifTrue: [
  1966                 ifTrue: [
  1967                         self addPrimaryTranslation: 'KL';
  1967                         self addPrimaryTranslation: 'KL';
  1968                         addSecondaryTranslation: 'L'.
  1968                         addSecondaryTranslation: 'L'.
  1969                         ^self incrementSkipCount: 1.
  1969                         ^self incrementSkipCount: 1.
  1970                 ].
  1970                 ].
  1971                 " //-ges-,-gep-,-gel-, -gie- at beginning
  1971                 " //-ges-,-gep-,-gel-, -gie- at beginning
  1972                 if((current == 0)
  1972                 if((current == 0)
  1973                 AND ((GetAt(current + 1) == 'Y') 
  1973                 AND ((GetAt(current + 1) == 'Y') 
  1974                 OR StringAt((current + 1), 2, ES, EP, EB, EL, EY, IB, IL, IN, IE, EI, ER, )) )"
  1974                 OR StringAt((current + 1), 2, ES, EP, EB, EL, EY, IB, IL, IN, IE, EI, ER, )) )"
  1975                 (self currentIndex = 1 and: [
  1975                 (currentIndex = 1 and: [
  1976                         ((self keyAt: self currentIndex + 1) = $Y) or: [
  1976                         ((self keyAt: currentIndex + 1) = $Y) or: [
  1977                         (#('ES' 'EP' 'EB' 'EL' 'EY' 'IB' 'IL' 'IN' 'IE' 'EI' 'ER') includes: 
  1977                         (#('ES' 'EP' 'EB' 'EL' 'EY' 'IB' 'IL' 'IN' 'IE' 'EI' 'ER') includes: 
  1978                                 (self inputKey copyFrom: self currentIndex + 1 to: self currentIndex + 2))
  1978                                 (self inputKey copyFrom: currentIndex + 1 to: currentIndex + 2))
  1979                 ]]) ifTrue: [
  1979                 ]]) ifTrue: [
  1980                         self addPrimaryTranslation: 'K';
  1980                         self addPrimaryTranslation: 'K';
  1981                         addSecondaryTranslation: 'J'.
  1981                         addSecondaryTranslation: 'J'.
  1982                         ^self incrementSkipCount: 1.
  1982                         ^self incrementSkipCount: 1.
  1983                 ].
  1983                 ].
  1985                 if((StringAt((current + 1), 2, ER, ) OR (GetAt(current + 1) == 'Y'))
  1985                 if((StringAt((current + 1), 2, ER, ) OR (GetAt(current + 1) == 'Y'))
  1986                 AND !!StringAt(0, 6, DANGER, RANGER, MANGER, )
  1986                 AND !!StringAt(0, 6, DANGER, RANGER, MANGER, )
  1987                 AND !!StringAt((current - 1), 1, E, I, ) 
  1987                 AND !!StringAt((current - 1), 1, E, I, ) 
  1988                 AND !!StringAt((current - 1), 3, RGY, OGY, ) )
  1988                 AND !!StringAt((current - 1), 3, RGY, OGY, ) )
  1989                 "
  1989                 "
  1990           (((self inputKey copyFrom: self currentIndex + 1 to: (self currentIndex + 3 min: self inputKey size)) = 'ER' or: [
  1990           (((self inputKey copyFrom: currentIndex + 1 to: (currentIndex + 3 min: self inputKey size)) = 'ER' or: [
  1991                                 ((self keyAt: self currentIndex + 1) = $Y)]) 
  1991                                 ((self keyAt: currentIndex + 1) = $Y)]) 
  1992                         and: [((#('DANGER' 'RANGER' 'MANGER') includes: (word := self inputKey copyFrom: 1 to: (6 min: self inputKey size))) not)
  1992                         and: [((#('DANGER' 'RANGER' 'MANGER') includes: (word := self inputKey copyFrom: 1 to: (6 min: self inputKey size))) not)
  1993                                 and: [(self keyAt: self currentIndex - 1) ~= $E
  1993                                 and: [(self keyAt: currentIndex - 1) ~= $E
  1994                                         and: [(#('RGY' 'OGY') includes: (self inputKey copyFrom: self currentIndex - 1 to: self currentIndex + 1)) not]]])
  1994                                         and: [(#('RGY' 'OGY') includes: (self inputKey copyFrom: currentIndex - 1 to: currentIndex + 1)) not]]])
  1995                  ifTrue: [
  1995                  ifTrue: [
  1996                         self addPrimaryTranslation: 'K';
  1996                         self addPrimaryTranslation: 'K';
  1997                         addSecondaryTranslation: 'J'.
  1997                         addSecondaryTranslation: 'J'.
  1998                         ^self incrementSkipCount: 1.
  1998                         ^self incrementSkipCount: 1.
  1999                 ].
  1999                 ].
  2000 
  2000 
  2001           " // italian e.g, 'biaggi'
  2001           " // italian e.g, 'biaggi'
  2002            if(StringAt((current + 1), 1, E, I, Y, ) OR StringAt((current - 1), 4, AGGI, OGGI, ))
  2002            if(StringAt((current + 1), 1, E, I, Y, ) OR StringAt((current - 1), 4, AGGI, OGGI, ))
  2003            "
  2003            "
  2004                 ((#($E $I $Y) includes: (self keyAt: (self currentIndex + 1))) or: [(#('AGGI' 'OGGI') includes: (self inputKey copyFrom: self currentIndex - 1 to: (self currentIndex + 2 min: self inputKey size)))])
  2004                 ((#($E $I $Y) includes: (self keyAt: (currentIndex + 1))) or: [(#('AGGI' 'OGGI') includes: (self inputKey copyFrom: currentIndex - 1 to: (currentIndex + 2 min: self inputKey size)))])
  2005                 ifTrue: [
  2005                 ifTrue: [
  2006                         " //obvious germanic
  2006                         " //obvious germanic
  2007                                         if((StringAt(0, 4, VAN , VON , ) OR StringAt(0, 3, SCH, ))
  2007                                         if((StringAt(0, 4, VAN , VON , ) OR StringAt(0, 3, SCH, ))
  2008                                                 OR StringAt((current + 1), 2, ET, ))                                                MetaphAdd(K);"
  2008                                                 OR StringAt((current + 1), 2, ET, ))                                                MetaphAdd(K);"
  2009                         word := (self inputKey copyFrom: 1 to: 4).
  2009                         word := (self inputKey copyFrom: 1 to: 4).
  2017                                                         MetaphAdd(J);
  2017                                                         MetaphAdd(J);
  2018                                                 else
  2018                                                 else
  2019                                                         MetaphAdd(J, K);
  2019                                                         MetaphAdd(J, K);
  2020                                         current += 2;
  2020                                         current += 2;
  2021                                         break;"
  2021                                         break;"
  2022                                 (((self inputKey copyFrom: self currentIndex + 1 to: (self currentIndex + 5 min: self inputKey size)), '    ') copyFrom: 1 to: 4) = 'IER '
  2022                                 (((self inputKey copyFrom: currentIndex + 1 to: (currentIndex + 5 min: self inputKey size)), '    ') copyFrom: 1 to: 4) = 'IER '
  2023                                 ifTrue: [
  2023                                 ifTrue: [
  2024                                         self addPrimaryTranslation: 'J';
  2024                                         self addPrimaryTranslation: 'J';
  2025                                         addSecondaryTranslation: 'J'.
  2025                                         addSecondaryTranslation: 'J'.
  2026                                 ] ifFalse: [
  2026                                 ] ifFalse: [
  2027                                         self addPrimaryTranslation: 'J';
  2027                                         self addPrimaryTranslation: 'J';
  2037          else
  2037          else
  2038              current += 1;
  2038              current += 1;
  2039          MetaphAdd(K);
  2039          MetaphAdd(K);
  2040             break;"
  2040             break;"
  2041 
  2041 
  2042                 (self keyAt: (self currentIndex + 1)) = $G
  2042                 (self keyAt: (currentIndex + 1)) = $G
  2043                 ifTrue: [
  2043                 ifTrue: [
  2044                         self incrementSkipCount: 1.
  2044                         self incrementSkipCount: 1.
  2045                 ].
  2045                 ].
  2046                 self addPrimaryTranslation: 'K';
  2046                 self addPrimaryTranslation: 'K';
  2047                 addSecondaryTranslation: 'K'.
  2047                 addSecondaryTranslation: 'K'.
  2048 !
  2048 !
  2049 
  2049 
  2050 processH
  2050 processH
  2051 	"http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2051         "http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2052 	case 'H':
  2052         case 'H':
  2053                                 //only keep if first & before vowel or btw. 2 vowels
  2053                                 //only keep if first & before vowel or btw. 2 vowels
  2054                                 if(((current == 0) OR IsVowel(current - 1)) 
  2054                                 if(((current == 0) OR IsVowel(current - 1)) 
  2055                                         AND IsVowel(current + 1))
  2055                                         AND IsVowel(current + 1))
  2056                                 {
  2056                                 {
  2057                                         MetaphAdd(H);
  2057                                         MetaphAdd(H);
  2059                                 }else//also takes care of 'HH'
  2059                                 }else//also takes care of 'HH'
  2060                                         current += 1;
  2060                                         current += 1;
  2061                                 break;
  2061                                 break;
  2062 "
  2062 "
  2063 
  2063 
  2064 	(((self currentIndex = 1) 
  2064         (((currentIndex = 1) 
  2065 		or: [ (self keyAt: self currentIndex - 1) isVowel]) 
  2065                 or: [ (self keyAt: currentIndex - 1) isVowel]) 
  2066 	and: [(self keyAt: self currentIndex + 1) isVowel])
  2066         and: [(self keyAt: currentIndex + 1) isVowel])
  2067 	ifTrue: [		
  2067         ifTrue: [               
  2068 		self addPrimaryTranslation: 'H';
  2068                 self addPrimaryTranslation: 'H';
  2069 		addSecondaryTranslation: 'H'.
  2069                 addSecondaryTranslation: 'H'.
  2070 		^self incrementSkipCount: 1.
  2070                 ^self incrementSkipCount: 1.
  2071 	]
  2071         ]
  2072 !
  2072 !
  2073 
  2073 
  2074 processJ
  2074 processJ
  2075 	"http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2075         "http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2076 	case 'J':
  2076         case 'J':
  2077                                 //obvious spanish, 'jose', 'san jacinto'
  2077                                 //obvious spanish, 'jose', 'san jacinto'
  2078                                 if(StringAt(current, 4, JOSE, ) OR StringAt(0, 4, SAN , ) )
  2078                                 if(StringAt(current, 4, JOSE, ) OR StringAt(0, 4, SAN , ) )
  2079                                 {
  2079                                 {
  2080                                         if(((current == 0) AND (GetAt(current + 4) == ' ')) OR StringAt(0, 4, SAN , ) )
  2080                                         if(((current == 0) AND (GetAt(current + 4) == ' ')) OR StringAt(0, 4, SAN , ) )
  2081                                                 MetaphAdd(H);
  2081                                                 MetaphAdd(H);
  2107                                         current += 2;
  2107                                         current += 2;
  2108                                 else
  2108                                 else
  2109                                         current += 1;
  2109                                         current += 1;
  2110                                 break;
  2110                                 break;
  2111 "
  2111 "
  2112 	| currentWord firstWord nextLetter |
  2112         | currentWord firstWord nextLetter |
  2113 	currentWord := self inputKey copyFrom: self currentIndex to: (self currentIndex + 3 min: self inputKey size).
  2113         currentWord := self inputKey copyFrom: currentIndex to: (currentIndex + 3 min: self inputKey size).
  2114 	firstWord := self inputKey copyFrom: 1 to: (4 min: self inputKey size).
  2114         firstWord := self inputKey copyFrom: 1 to: (4 min: self inputKey size).
  2115 	nextLetter := self keyAt: self currentIndex + 1.
  2115         nextLetter := self keyAt: currentIndex + 1.
  2116 	(currentWord = 'JOSE' or: [firstWord = 'SAN '])
  2116         (currentWord = 'JOSE' or: [firstWord = 'SAN '])
  2117 	ifTrue: [	
  2117         ifTrue: [       
  2118 		((self currentIndex = 1 and: [self inputKey size = 4 or: [self inputKey size >= 5 and: [self keyAt: self currentIndex + 4 = $ ]]])
  2118                 ((currentIndex = 1 and: [self inputKey size = 4 or: [self inputKey size >= 5 and: [self keyAt: currentIndex + 4 = $ ]]])
  2119 			or: [firstWord = 'SAN '])
  2119                         or: [firstWord = 'SAN '])
  2120 		ifTrue: [
  2120                 ifTrue: [
  2121 			self addPrimaryTranslation: 'H';
  2121                         self addPrimaryTranslation: 'H';
  2122 			addSecondaryTranslation: 'H'.
  2122                         addSecondaryTranslation: 'H'.
  2123 		] ifFalse: [
  2123                 ] ifFalse: [
  2124 			self addPrimaryTranslation: 'J';
  2124                         self addPrimaryTranslation: 'J';
  2125 			addSecondaryTranslation: 'H'.
  2125                         addSecondaryTranslation: 'H'.
  2126 		].
  2126                 ].
  2127 		^self.
  2127                 ^self.
  2128 	].
  2128         ].
  2129 	(self currentIndex = 1 and: [firstWord ~= 'JOSE'])
  2129         (currentIndex = 1 and: [firstWord ~= 'JOSE'])
  2130 	ifTrue: [
  2130         ifTrue: [
  2131 		self addPrimaryTranslation: 'J';
  2131                 self addPrimaryTranslation: 'J';
  2132 		addSecondaryTranslation: 'A'.
  2132                 addSecondaryTranslation: 'A'.
  2133 	] ifFalse: [
  2133         ] ifFalse: [
  2134 		((self currentIndex > 1 and: [(self keyAt: self currentIndex -1) isVowel])
  2134                 ((currentIndex > 1 and: [(self keyAt: currentIndex -1) isVowel])
  2135 		and: [(self isSlavoGermanic: self inputKey) not and: [nextLetter = $A or: [nextLetter = $O]]])
  2135                 and: [(self isSlavoGermanic: self inputKey) not and: [nextLetter = $A or: [nextLetter = $O]]])
  2136 		ifTrue: [
  2136                 ifTrue: [
  2137 			self addPrimaryTranslation: 'J';
  2137                         self addPrimaryTranslation: 'J';
  2138 			addSecondaryTranslation: 'H'.
  2138                         addSecondaryTranslation: 'H'.
  2139 		] ifFalse: [
  2139                 ] ifFalse: [
  2140 			currentIndex = self inputKey size 
  2140                         currentIndex = self inputKey size 
  2141 			ifTrue: [
  2141                         ifTrue: [
  2142 				self addPrimaryTranslation: 'J';
  2142                                 self addPrimaryTranslation: 'J';
  2143 				addSecondaryTranslation: ' '.
  2143                                 addSecondaryTranslation: ' '.
  2144 			] ifFalse: [
  2144                         ] ifFalse: [
  2145 				((#($L $T $K $S $N $M $B $Z) includes: nextLetter) not and: [(#($S $K $L) includes: (self keyAt: self currentIndex - 1)) not])
  2145                                 ((#($L $T $K $S $N $M $B $Z) includes: nextLetter) not and: [(#($S $K $L) includes: (self keyAt: currentIndex - 1)) not])
  2146 				ifTrue: [
  2146                                 ifTrue: [
  2147 					self addPrimaryTranslation: 'J';
  2147                                         self addPrimaryTranslation: 'J';
  2148 					addSecondaryTranslation: 'J'.
  2148                                         addSecondaryTranslation: 'J'.
  2149 				].
  2149                                 ].
  2150 			].
  2150                         ].
  2151 		].
  2151                 ].
  2152 	].
  2152         ].
  2153 	nextLetter = $J
  2153         nextLetter = $J
  2154 	ifTrue: [
  2154         ifTrue: [
  2155 		self incrementSkipCount: 1.
  2155                 self incrementSkipCount: 1.
  2156 	].
  2156         ].
  2157 		
       
  2158 !
  2157 !
  2159 
  2158 
  2160 processK
  2159 processK
  2161 	"http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2160         "http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2162 	case 'K':
  2161         case 'K':
  2163                                 if(GetAt(current + 1) == 'K')
  2162                                 if(GetAt(current + 1) == 'K')
  2164                                         current += 2;
  2163                                         current += 2;
  2165                                 else
  2164                                 else
  2166                                         current += 1;
  2165                                         current += 1;
  2167                                 MetaphAdd(K);
  2166                                 MetaphAdd(K);
  2168                                 break;
  2167                                 break;
  2169 	"
  2168         "
  2170 
  2169 
  2171 	(self keyAt: self currentIndex + 1) = $K
  2170         (self keyAt: currentIndex + 1) = $K
  2172 	ifTrue: [
  2171         ifTrue: [
  2173 		self incrementSkipCount: 1
  2172                 self incrementSkipCount: 1
  2174 	].
  2173         ].
  2175 	self addPrimaryTranslation: 'K';
  2174         self addPrimaryTranslation: 'K';
  2176 	addSecondaryTranslation: 'K'.
  2175         addSecondaryTranslation: 'K'.
  2177 		
       
  2178 !
  2176 !
  2179 
  2177 
  2180 processL
  2178 processL
  2181 
  2179 
  2182 "case 'L':
  2180 "case 'L':
  2196                                 }else
  2194                                 }else
  2197                                         current += 1;
  2195                                         current += 1;
  2198                                 MetaphAdd(L);
  2196                                 MetaphAdd(L);
  2199                                 break;
  2197                                 break;
  2200 "
  2198 "
  2201 	| currentWord |
  2199         | currentWord |
  2202 	(self keyAt: self currentIndex + 1) = $L 
  2200         (self keyAt: currentIndex + 1) = $L 
  2203 	ifTrue: [
  2201         ifTrue: [
  2204 		(((self currentIndex = (self inputKey size - 2))
  2202                 (((currentIndex = (self inputKey size - 2))
  2205 		and: [(self currentIndex > 1 and: [#('ILLO' 'ILLA' 'ALLE') includes: (currentWord := self inputKey copyFrom: self currentIndex - 1 to: (self currentIndex + 2 min: self inputKey size))])])
  2203                 and: [(currentIndex > 1 and: [#('ILLO' 'ILLA' 'ALLE') includes: (currentWord := self inputKey copyFrom: currentIndex - 1 to: (currentIndex + 2 min: self inputKey size))])])
  2206 		or: [((#('AS' 'OS') includes: (self inputKey copyFrom: self inputKey size - 1 to: self inputKey size)) or: [#($A $O) includes: (self keyAt: self inputKey size)]) and: [currentWord = 'ALLE']
  2204                 or: [((#('AS' 'OS') includes: (self inputKey copyFrom: self inputKey size - 1 to: self inputKey size)) or: [#($A $O) includes: (self keyAt: self inputKey size)]) and: [currentWord = 'ALLE']
  2207 			])
  2205                         ])
  2208 		ifTrue: [
  2206                 ifTrue: [
  2209 			self addPrimaryTranslation: 'L';
  2207                         self addPrimaryTranslation: 'L';
  2210 			addSecondaryTranslation: ' '.
  2208                         addSecondaryTranslation: ' '.
  2211 			^self incrementSkipCount: 1.
  2209                         ^self incrementSkipCount: 1.
  2212 		].
  2210                 ].
  2213 		self incrementSkipCount: 1.
  2211                 self incrementSkipCount: 1.
  2214 	].
  2212         ].
  2215 	self addPrimaryTranslation: 'L';
  2213         self addPrimaryTranslation: 'L';
  2216 	addSecondaryTranslation: 'L'.	
  2214         addSecondaryTranslation: 'L'.   
  2217 		
       
  2218 		
       
  2219 !
  2215 !
  2220 
  2216 
  2221 processM
  2217 processM
  2222 
  2218 
  2223 "case 'M':
  2219 "case 'M':
  2229                                 else
  2225                                 else
  2230                                         current += 1;
  2226                                         current += 1;
  2231                                 MetaphAdd(M);
  2227                                 MetaphAdd(M);
  2232                                 break;
  2228                                 break;
  2233 "
  2229 "
  2234 	(((self currentIndex > 1 and: [(self inputKey copyFrom: self currentIndex - 1 to: (self currentIndex +1 min: self inputKey size)) = 'UMB'])
  2230         (((currentIndex > 1 and: [(self inputKey copyFrom: currentIndex - 1 to: (currentIndex +1 min: self inputKey size)) = 'UMB'])
  2235 		and: [self currentIndex + 1 = self inputKey size or: [(self inputKey copyFrom: (self currentIndex + 2 min: self inputKey size) to: (self currentIndex + 4 min: self inputKey size)) = 'ER']])
  2231                 and: [currentIndex + 1 = self inputKey size or: [(self inputKey copyFrom: (currentIndex + 2 min: self inputKey size) to: (currentIndex + 4 min: self inputKey size)) = 'ER']])
  2236 		or: [(self keyAt: self currentIndex + 1) = $M])
  2232                 or: [(self keyAt: currentIndex + 1) = $M])
  2237 		ifTrue: [
  2233                 ifTrue: [
  2238 			self incrementSkipCount: 1.
  2234                         self incrementSkipCount: 1.
  2239 		].
  2235                 ].
  2240 		self addPrimaryTranslation: 'M';
  2236                 self addPrimaryTranslation: 'M';
  2241 		addSecondaryTranslation: 'M'.
  2237                 addSecondaryTranslation: 'M'.
  2242 		
       
  2243 !
  2238 !
  2244 
  2239 
  2245 processN
  2240 processN
  2246 	"http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2241         "http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2247 	case 'N':
  2242         case 'N':
  2248                                 if(GetAt(current + 1) == 'N')
  2243                                 if(GetAt(current + 1) == 'N')
  2249                                         current += 2;
  2244                                         current += 2;
  2250                                 else
  2245                                 else
  2251                                         current += 1;
  2246                                         current += 1;
  2252                                 MetaphAdd(N);
  2247                                 MetaphAdd(N);
  2253                                 break;
  2248                                 break;
  2254 
  2249 
  2255 	"
  2250         "
  2256 
  2251 
  2257 	(self keyAt: self currentIndex + 1) = $N
  2252         (self keyAt: currentIndex + 1) = $N
  2258 	ifTrue: [
  2253         ifTrue: [
  2259 		self incrementSkipCount: 1
  2254                 self incrementSkipCount: 1
  2260 	].
  2255         ].
  2261 	self addPrimaryTranslation: 'N';
  2256         self addPrimaryTranslation: 'N';
  2262 	addSecondaryTranslation: 'N'.
  2257         addSecondaryTranslation: 'N'.
  2263 		
       
  2264 !
  2258 !
  2265 
  2259 
  2266 processNtilde
  2260 processNtilde
  2267         "case 'Ñ':
  2261         "case 'Ñ':
  2268                                 current += 1;
  2262                                 current += 1;
  2272         self addPrimaryTranslation: 'N';
  2266         self addPrimaryTranslation: 'N';
  2273         addSecondaryTranslation: 'N'.
  2267         addSecondaryTranslation: 'N'.
  2274 !
  2268 !
  2275 
  2269 
  2276 processP
  2270 processP
  2277 	"case 'P':
  2271         "case 'P':
  2278                                 if(GetAt(current + 1) == 'H')
  2272                                 if(GetAt(current + 1) == 'H')
  2279                                 {
  2273                                 {
  2280                                         MetaphAdd(F);
  2274                                         MetaphAdd(F);
  2281                                         current += 2;
  2275                                         current += 2;
  2282                                         break;
  2276                                         break;
  2288                                 else
  2282                                 else
  2289                                         current += 1;
  2283                                         current += 1;
  2290                                         MetaphAdd(P);
  2284                                         MetaphAdd(P);
  2291                                 break;
  2285                                 break;
  2292 "
  2286 "
  2293 	| nextLetter |
  2287         | nextLetter |
  2294 	(nextLetter := self keyAt: self currentIndex + 1) = $H
  2288         (nextLetter := self keyAt: currentIndex + 1) = $H
  2295 	ifTrue: [
  2289         ifTrue: [
  2296 		self addPrimaryTranslation: 'F';
  2290                 self addPrimaryTranslation: 'F';
  2297 		addSecondaryTranslation: 'F'.
  2291                 addSecondaryTranslation: 'F'.
  2298 		^self incrementSkipCount: 1.
  2292                 ^self incrementSkipCount: 1.
  2299 	].
  2293         ].
  2300 	(#($P $B) includes: nextLetter)
  2294         (#($P $B) includes: nextLetter)
  2301 	ifTrue: [
  2295         ifTrue: [
  2302 		self incrementSkipCount: 1.
  2296                 self incrementSkipCount: 1.
  2303 	] ifFalse: [
  2297         ] ifFalse: [
  2304 		self addPrimaryTranslation: 'P';
  2298                 self addPrimaryTranslation: 'P';
  2305 		addSecondaryTranslation: 'P'.
  2299                 addSecondaryTranslation: 'P'.
  2306 	].
  2300         ].
  2307 !
  2301 !
  2308 
  2302 
  2309 processQ
  2303 processQ
  2310 	"http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2304         "http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2311 	case 'Q':
  2305         case 'Q':
  2312                                 if(GetAt(current + 1) == 'Q')
  2306                                 if(GetAt(current + 1) == 'Q')
  2313                                         current += 2;
  2307                                         current += 2;
  2314                                 else
  2308                                 else
  2315                                         current += 1;
  2309                                         current += 1;
  2316                                 MetaphAdd(K);
  2310                                 MetaphAdd(K);
  2317                                 break;
  2311                                 break;
  2318 
  2312 
  2319 	"
  2313         "
  2320 
  2314 
  2321 	(self keyAt: self currentIndex + 1) = $Q
  2315         (self keyAt: currentIndex + 1) = $Q
  2322 	ifTrue: [
  2316         ifTrue: [
  2323 		self incrementSkipCount: 1
  2317                 self incrementSkipCount: 1
  2324 	].
  2318         ].
  2325 	self addPrimaryTranslation: 'K';
  2319         self addPrimaryTranslation: 'K';
  2326 	addSecondaryTranslation: 'K'.
  2320         addSecondaryTranslation: 'K'.
  2327 		
       
  2328 !
  2321 !
  2329 
  2322 
  2330 processR
  2323 processR
  2331 	"http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2324         "http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2332 	case 'R':
  2325         case 'R':
  2333                                 //french e.g. 'rogier', but exclude 'hochmeier'
  2326                                 //french e.g. 'rogier', but exclude 'hochmeier'
  2334                                 if((current == last)
  2327                                 if((current == last)
  2335                                         AND !!SlavoGermanic()
  2328                                         AND !!SlavoGermanic()
  2336                                                 AND StringAt((current - 2), 2, IE, ) 
  2329                                                 AND StringAt((current - 2), 2, IE, ) 
  2337                                                         AND !!StringAt((current - 4), 2, ME, MA, ))
  2330                                                         AND !!StringAt((current - 4), 2, ME, MA, ))
  2342                                 if(GetAt(current + 1) == 'R')
  2335                                 if(GetAt(current + 1) == 'R')
  2343                                         current += 2;
  2336                                         current += 2;
  2344                                 else
  2337                                 else
  2345                                         current += 1;
  2338                                         current += 1;
  2346                                 break;
  2339                                 break;
  2347 	"
  2340         "
  2348 	(self currentIndex = self inputKey size and: [
  2341         (currentIndex = self inputKey size and: [
  2349 		(self isSlavoGermanic: self inputKey) not and: [
  2342                 (self isSlavoGermanic: self inputKey) not and: [
  2350 			(self inputKey copyFrom: ((self currentIndex - 2) max: 1) to: ((self currentIndex - 1) max: 1)) = 'IE' and: [
  2343                         (self inputKey copyFrom: ((currentIndex - 2) max: 1) to: ((currentIndex - 1) max: 1)) = 'IE' and: [
  2351 				(#('ME' 'MA') includes: (self inputKey copyFrom: ((self currentIndex - 4) max: 1) to: ((self currentIndex - 3) max: 1))) not
  2344                                 (#('ME' 'MA') includes: (self inputKey copyFrom: ((currentIndex - 4) max: 1) to: ((currentIndex - 3) max: 1))) not
  2352 			]
  2345                         ]
  2353 		]
  2346                 ]
  2354 	])
  2347         ])
  2355 	ifTrue: [
  2348         ifTrue: [
  2356 		self addPrimaryTranslation: '';
  2349                 self addPrimaryTranslation: '';
  2357 		addSecondaryTranslation: 'R'.
  2350                 addSecondaryTranslation: 'R'.
  2358 	] ifFalse: [
  2351         ] ifFalse: [
  2359 		self addPrimaryTranslation: 'R';
  2352                 self addPrimaryTranslation: 'R';
  2360 		addSecondaryTranslation: 'R'.
  2353                 addSecondaryTranslation: 'R'.
  2361 	].
  2354         ].
  2362 	(self keyAt: self currentIndex + 1) = $R
  2355         (self keyAt: currentIndex + 1) = $R
  2363 	ifTrue: [
  2356         ifTrue: [
  2364 		self incrementSkipCount: 1
  2357                 self incrementSkipCount: 1
  2365 	].
  2358         ].
  2366 	
       
  2367 		
       
  2368 !
  2359 !
  2369 
  2360 
  2370 processRemainingCharacters
  2361 processRemainingCharacters
  2371     self startIndex to: self inputKey size do:[ :i | 
  2362     self startIndex to: self inputKey size do:[ :i | 
  2372         | c methodSelector |
  2363         | c methodSelector |
  2393         ] 
  2384         ] 
  2394     ]
  2385     ]
  2395 !
  2386 !
  2396 
  2387 
  2397 processS
  2388 processS
  2398 	"http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2389         "http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2399 	case 'S':
  2390         case 'S':
  2400                                 //special cases 'island', 'isle', 'carlisle', 'carlysle'
  2391                                 //special cases 'island', 'isle', 'carlisle', 'carlysle'
  2401                                 if(StringAt((current - 1), 3, ISL, YSL, ))
  2392                                 if(StringAt((current - 1), 3, ISL, YSL, ))
  2402                                 {
  2393                                 {
  2403                                         current += 1;
  2394                                         current += 1;
  2404                                         break;
  2395                                         break;
  2495                                 else
  2486                                 else
  2496                                         current += 1;
  2487                                         current += 1;
  2497                                 break;
  2488                                 break;
  2498 "
  2489 "
  2499 
  2490 
  2500 	| nextChar char2 chars char |
  2491         | nextChar char2 chars char |
  2501 	(#('ISL' 'YSL') includes: (self inputKey copyFrom: (self currentIndex - 1 max: 1) to: (self currentIndex + 1 min: self inputKey size))) 
  2492         (#('ISL' 'YSL') includes: (self inputKey copyFrom: (currentIndex - 1 max: 1) to: (currentIndex + 1 min: self inputKey size))) 
  2502 	ifTrue: [
  2493         ifTrue: [
  2503 		^self
  2494                 ^self
  2504 	].
  2495         ].
  2505 	(self currentIndex = 1 and: [(self inputKey copyFrom: 1 to: (5 min: self inputKey size)) = 'SUGAR'])
  2496         (currentIndex = 1 and: [(self inputKey copyFrom: 1 to: (5 min: self inputKey size)) = 'SUGAR'])
  2506 	ifTrue: [
  2497         ifTrue: [
  2507 		self addPrimaryTranslation: 'X';
  2498                 self addPrimaryTranslation: 'X';
  2508 		addSecondaryTranslation: 'S'.
  2499                 addSecondaryTranslation: 'S'.
  2509 		^self.
  2500                 ^self.
  2510 	].
  2501         ].
  2511 	(self inputKey copyFrom: self currentIndex to: ((self currentIndex + 1) min: self inputKey size)) = 'SH'
  2502         (self inputKey copyFrom: currentIndex to: ((currentIndex + 1) min: self inputKey size)) = 'SH'
  2512 	ifTrue: [
  2503         ifTrue: [
  2513 		(#('HEIM' 'HOEK' 'HOLM' 'HOLZ') includes: (self inputKey copyFrom: (self currentIndex + 1 min: self inputKey size) to: ((self currentIndex + 5) min: self inputKey size)))
  2504                 (#('HEIM' 'HOEK' 'HOLM' 'HOLZ') includes: (self inputKey copyFrom: (currentIndex + 1 min: self inputKey size) to: ((currentIndex + 5) min: self inputKey size)))
  2514 		ifTrue: [
  2505                 ifTrue: [
  2515 			self addPrimaryTranslation: 'S';
  2506                         self addPrimaryTranslation: 'S';
  2516 			addSecondaryTranslation: 'S'.
  2507                         addSecondaryTranslation: 'S'.
  2517 		] ifFalse: [
  2508                 ] ifFalse: [
  2518 			self addPrimaryTranslation: 'X';
  2509                         self addPrimaryTranslation: 'X';
  2519 			addSecondaryTranslation: 'X'.
  2510                         addSecondaryTranslation: 'X'.
  2520 		].
  2511                 ].
  2521 		^self incrementSkipCount: 1
  2512                 ^self incrementSkipCount: 1
  2522 	].
  2513         ].
  2523 	((#('SIO' 'SIA') includes: (self inputKey copyFrom: self currentIndex to: (self currentIndex + 2 min: self inputKey size)))
  2514         ((#('SIO' 'SIA') includes: (self inputKey copyFrom: currentIndex to: (currentIndex + 2 min: self inputKey size)))
  2524 		or: [(self inputKey copyFrom: self currentIndex to: (self currentIndex + 3 min: self inputKey size)) = 'SIAN'])
  2515                 or: [(self inputKey copyFrom: currentIndex to: (currentIndex + 3 min: self inputKey size)) = 'SIAN'])
  2525 	ifTrue: [
  2516         ifTrue: [
  2526 		(self isSlavoGermanic: self inputKey) not
  2517                 (self isSlavoGermanic: self inputKey) not
  2527 		ifTrue: [
  2518                 ifTrue: [
  2528 			self addPrimaryTranslation: 'S';
  2519                         self addPrimaryTranslation: 'S';
  2529 			addSecondaryTranslation: 'X'.
  2520                         addSecondaryTranslation: 'X'.
  2530 		] ifFalse: [
  2521                 ] ifFalse: [
  2531 			self addPrimaryTranslation: 'S';
  2522                         self addPrimaryTranslation: 'S';
  2532 			addSecondaryTranslation: 'S'.
  2523                         addSecondaryTranslation: 'S'.
  2533 		].
  2524                 ].
  2534 		^self incrementSkipCount: 2
  2525                 ^self incrementSkipCount: 2
  2535 	].
  2526         ].
  2536 	((self currentIndex = 1 and: [#($M $N $L $W) includes: (self keyAt: self currentIndex + 1)])
  2527         ((currentIndex = 1 and: [#($M $N $L $W) includes: (self keyAt: currentIndex + 1)])
  2537 		or: [(nextChar := self keyAt: self currentIndex + 1) = $Z])
  2528                 or: [(nextChar := self keyAt: currentIndex + 1) = $Z])
  2538 	ifTrue: [
  2529         ifTrue: [
  2539 		self addPrimaryTranslation: 'S';
  2530                 self addPrimaryTranslation: 'S';
  2540 		addSecondaryTranslation: 'X'.
  2531                 addSecondaryTranslation: 'X'.
  2541 		nextChar = $Z
  2532                 nextChar = $Z
  2542 		ifTrue: [
  2533                 ifTrue: [
  2543 			^self incrementSkipCount: 1.
  2534                         ^self incrementSkipCount: 1.
  2544 		].
  2535                 ].
  2545 		^self.
  2536                 ^self.
  2546 	].
  2537         ].
  2547 	((self inputKey copyFrom: self currentIndex to: ((self currentIndex + 1) min: self inputKey size)) = 'SC')
  2538         ((self inputKey copyFrom: currentIndex to: ((currentIndex + 1) min: self inputKey size)) = 'SC')
  2548 	ifTrue: [
  2539         ifTrue: [
  2549 		(char2 := self keyAt: self currentIndex + 2) = $H
  2540                 (char2 := self keyAt: currentIndex + 2) = $H
  2550 		ifTrue: [
  2541                 ifTrue: [
  2551 			(#('OO' 'ER' 'EN' 'UY' 'ED' 'EM') includes: (chars := self inputKey copyFrom: ((self currentIndex + 3) min: self inputKey size) to: ((self currentIndex + 4) min: self inputKey size)))
  2542                         (#('OO' 'ER' 'EN' 'UY' 'ED' 'EM') includes: (chars := self inputKey copyFrom: ((currentIndex + 3) min: self inputKey size) to: ((currentIndex + 4) min: self inputKey size)))
  2552 			ifTrue: [
  2543                         ifTrue: [
  2553 				(#('ER' 'EN') includes: chars)
  2544                                 (#('ER' 'EN') includes: chars)
  2554 				ifTrue: [
  2545                                 ifTrue: [
  2555 					self addPrimaryTranslation: 'X';
  2546                                         self addPrimaryTranslation: 'X';
  2556 					addSecondaryTranslation: 'SK'.
  2547                                         addSecondaryTranslation: 'SK'.
  2557 				] ifFalse: [
  2548                                 ] ifFalse: [
  2558 					self addPrimaryTranslation: 'SK';
  2549                                         self addPrimaryTranslation: 'SK';
  2559 					addSecondaryTranslation: 'SK'.
  2550                                         addSecondaryTranslation: 'SK'.
  2560 				].
  2551                                 ].
  2561 				^self incrementSkipCount: 2.
  2552                                 ^self incrementSkipCount: 2.
  2562 			] ifFalse: [
  2553                         ] ifFalse: [
  2563 				((self currentIndex = 1 and: [(char := self inputKey at: 4 ifAbsent: [$b]) isVowel not]) and: [char ~= $W])
  2554                                 ((currentIndex = 1 and: [(char := self inputKey at: 4 ifAbsent: [$b]) isVowel not]) and: [char ~= $W])
  2564 				ifTrue: [
  2555                                 ifTrue: [
  2565 					self addPrimaryTranslation: 'X';
  2556                                         self addPrimaryTranslation: 'X';
  2566 					addSecondaryTranslation: 'S'.
  2557                                         addSecondaryTranslation: 'S'.
  2567 				] ifFalse: [
  2558                                 ] ifFalse: [
  2568 					self addPrimaryTranslation: 'X';
  2559                                         self addPrimaryTranslation: 'X';
  2569 					addSecondaryTranslation: 'X'.
  2560                                         addSecondaryTranslation: 'X'.
  2570 				].
  2561                                 ].
  2571 				^self incrementSkipCount: 2.
  2562                                 ^self incrementSkipCount: 2.
  2572 			].
  2563                         ].
  2573 		] ifFalse: [
  2564                 ] ifFalse: [
  2574 			(#($I $E $Y) includes: char2)
  2565                         (#($I $E $Y) includes: char2)
  2575 			ifTrue: [
  2566                         ifTrue: [
  2576 				self addPrimaryTranslation: 'S';
  2567                                 self addPrimaryTranslation: 'S';
  2577 				addSecondaryTranslation: 'S'.
  2568                                 addSecondaryTranslation: 'S'.
  2578 				^self incrementSkipCount: 2.
  2569                                 ^self incrementSkipCount: 2.
  2579 			] ifFalse: [
  2570                         ] ifFalse: [
  2580 				self addPrimaryTranslation: 'SK';
  2571                                 self addPrimaryTranslation: 'SK';
  2581 				addSecondaryTranslation: 'SK'.
  2572                                 addSecondaryTranslation: 'SK'.
  2582 				^self incrementSkipCount: 2.
  2573                                 ^self incrementSkipCount: 2.
  2583 			]
  2574                         ]
  2584 		].
  2575                 ].
  2585 	].
  2576         ].
  2586  	(self currentIndex = self inputKey size and: [(#('AI' 'OI') includes: (self inputKey copyFrom: ((self currentIndex - 2) max: 1) to: ((self currentIndex - 1) max: 1)))])
  2577         (currentIndex = self inputKey size and: [(#('AI' 'OI') includes: (self inputKey copyFrom: ((currentIndex - 2) max: 1) to: ((currentIndex - 1) max: 1)))])
  2587 	ifTrue: [
  2578         ifTrue: [
  2588 		self addPrimaryTranslation: '';
  2579                 self addPrimaryTranslation: '';
  2589 		addSecondaryTranslation: 'S'.
  2580                 addSecondaryTranslation: 'S'.
  2590 	] ifFalse: [
  2581         ] ifFalse: [
  2591 		self addPrimaryTranslation: 'S';
  2582                 self addPrimaryTranslation: 'S';
  2592 		addSecondaryTranslation: 'S'.
  2583                 addSecondaryTranslation: 'S'.
  2593 	].
  2584         ].
  2594 	(#($S $Z) includes: (self keyAt: self currentIndex + 1))
  2585         (#($S $Z) includes: (self keyAt: currentIndex + 1))
  2595 	ifTrue: [
  2586         ifTrue: [
  2596 		^self incrementSkipCount: 1.
  2587                 ^self incrementSkipCount: 1.
  2597 	].
  2588         ].
  2598 !
  2589 !
  2599 
  2590 
  2600 processT
  2591 processT
  2601 	"http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2592         "http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2602 	case 'T':
  2593         case 'T':
  2603                                 if(StringAt(current, 4, TION, ))
  2594                                 if(StringAt(current, 4, TION, ))
  2604                                 {
  2595                                 {
  2605                                         MetaphAdd(X);
  2596                                         MetaphAdd(X);
  2606                                         current += 3;
  2597                                         current += 3;
  2607                                         break;
  2598                                         break;
  2635                                 else
  2626                                 else
  2636                                         current += 1;
  2627                                         current += 1;
  2637                                 MetaphAdd(T);
  2628                                 MetaphAdd(T);
  2638                                 break;
  2629                                 break;
  2639 "
  2630 "
  2640 	((self inputKey copyFrom: self currentIndex to: ((self currentIndex + 3) min: self inputKey size)) = 'TION')
  2631         ((self inputKey copyFrom: currentIndex to: ((currentIndex + 3) min: self inputKey size)) = 'TION')
  2641 	ifTrue: [
  2632         ifTrue: [
  2642 		self addPrimaryTranslation: 'X';
  2633                 self addPrimaryTranslation: 'X';
  2643 		addSecondaryTranslation: 'X'.	
  2634                 addSecondaryTranslation: 'X'.   
  2644 		^self incrementSkipCount: 2.
  2635                 ^self incrementSkipCount: 2.
  2645 	].
  2636         ].
  2646 	(#('TIA' 'TCH') includes: (self inputKey copyFrom: self currentIndex to: ((self currentIndex + 2) min: self inputKey size)))
  2637         (#('TIA' 'TCH') includes: (self inputKey copyFrom: currentIndex to: ((currentIndex + 2) min: self inputKey size)))
  2647 	ifTrue: [
  2638         ifTrue: [
  2648 		self addPrimaryTranslation: 'X';
  2639                 self addPrimaryTranslation: 'X';
  2649 		addSecondaryTranslation: 'X'.	
  2640                 addSecondaryTranslation: 'X'.   
  2650 		^self incrementSkipCount: 2.
  2641                 ^self incrementSkipCount: 2.
  2651 	].
  2642         ].
  2652 	(((self inputKey copyFrom: self currentIndex to: ((self currentIndex + 1) min: self inputKey size)) = 'TH') or: [
  2643         (((self inputKey copyFrom: currentIndex to: ((currentIndex + 1) min: self inputKey size)) = 'TH') or: [
  2653 		((self inputKey copyFrom: self currentIndex to: ((self currentIndex + 2) min: self inputKey size)) = 'TTH')
  2644                 ((self inputKey copyFrom: currentIndex to: ((currentIndex + 2) min: self inputKey size)) = 'TTH')
  2654 	])
  2645         ])
  2655 	ifTrue: [
  2646         ifTrue: [
  2656 		((#('OM' 'AM') includes: (self inputKey copyFrom: self currentIndex + 2 to: ((self currentIndex + 3) min: self inputKey size)))
  2647                 ((#('OM' 'AM') includes: (self inputKey copyFrom: currentIndex + 2 to: ((currentIndex + 3) min: self inputKey size)))
  2657 		or: [(#('VAN ' 'VON ') includes: (self inputKey copyFrom: 1 to: (4 min: self inputKey size)))
  2648                 or: [(#('VAN ' 'VON ') includes: (self inputKey copyFrom: 1 to: (4 min: self inputKey size)))
  2658 			or: [(self inputKey copyFrom: 1 to: (3 min: self inputKey size)) = 'SCH']
  2649                         or: [(self inputKey copyFrom: 1 to: (3 min: self inputKey size)) = 'SCH']
  2659 			])
  2650                         ])
  2660 		ifTrue: [
  2651                 ifTrue: [
  2661 			self addPrimaryTranslation: 'T';
  2652                         self addPrimaryTranslation: 'T';
  2662 			addSecondaryTranslation: 'T'.	
  2653                         addSecondaryTranslation: 'T'.   
  2663 		] ifFalse: [
  2654                 ] ifFalse: [
  2664 			self addPrimaryTranslation: '0';
  2655                         self addPrimaryTranslation: '0';
  2665 			addSecondaryTranslation: 'T'.	
  2656                         addSecondaryTranslation: 'T'.   
  2666 		].
  2657                 ].
  2667 		^self incrementSkipCount: 1.
  2658                 ^self incrementSkipCount: 1.
  2668 	].
  2659         ].
  2669 	(#($T $D) includes: (self keyAt: self currentIndex + 1))
  2660         (#($T $D) includes: (self keyAt: currentIndex + 1))
  2670 	ifTrue: [
  2661         ifTrue: [
  2671 		self incrementSkipCount: 1.
  2662                 self incrementSkipCount: 1.
  2672 	].
  2663         ].
  2673 	self addPrimaryTranslation: 'T';
  2664         self addPrimaryTranslation: 'T';
  2674 	addSecondaryTranslation: 'T'.	
  2665         addSecondaryTranslation: 'T'.   
  2675 	
       
  2676 !
  2666 !
  2677 
  2667 
  2678 processV
  2668 processV
  2679 	"http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2669         "http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2680 	case 'V':
  2670         case 'V':
  2681                                 if(GetAt(current + 1) == 'V')
  2671                                 if(GetAt(current + 1) == 'V')
  2682                                         current += 2;
  2672                                         current += 2;
  2683                                 else
  2673                                 else
  2684                                         current += 1;
  2674                                         current += 1;
  2685                                 MetaphAdd(F);
  2675                                 MetaphAdd(F);
  2686                                 break;
  2676                                 break;
  2687 
  2677 
  2688 
  2678 
  2689 	"
  2679         "
  2690 
  2680 
  2691 	(self keyAt: self currentIndex + 1) = $V
  2681         (self keyAt: currentIndex + 1) = $V
  2692 	ifTrue: [
  2682         ifTrue: [
  2693 		self incrementSkipCount: 1
  2683                 self incrementSkipCount: 1
  2694 	].
  2684         ].
  2695 	self addPrimaryTranslation: 'F';
  2685         self addPrimaryTranslation: 'F';
  2696 	addSecondaryTranslation: 'F'.
  2686         addSecondaryTranslation: 'F'.
  2697 		
       
  2698 !
  2687 !
  2699 
  2688 
  2700 processW
  2689 processW
  2701 	"http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2690         "http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2702 	case 'W':
  2691         case 'W':
  2703                                 //can also be in middle of word
  2692                                 //can also be in middle of word
  2704                                 if(StringAt(current, 2, WR, ))
  2693                                 if(StringAt(current, 2, WR, ))
  2705                                 {
  2694                                 {
  2706                                         MetaphAdd(R);
  2695                                         MetaphAdd(R);
  2707                                         current += 2;
  2696                                         current += 2;
  2721 
  2710 
  2722                                 //Arnow should match Arnoff
  2711                                 //Arnow should match Arnoff
  2723                                 if(((current == last) AND IsVowel(current - 1)) 
  2712                                 if(((current == last) AND IsVowel(current - 1)) 
  2724                                         OR StringAt((current - 1), 5, EWSKI, EWSKY, OWSKI, OWSKY, ) 
  2713                                         OR StringAt((current - 1), 5, EWSKI, EWSKY, OWSKI, OWSKY, ) 
  2725                                                         OR StringAt(0, 3, SCH, ))
  2714                                                         OR StringAt(0, 3, SCH, ))
  2726 				  {
  2715                                   {
  2727                                         MetaphAdd(, F);
  2716                                         MetaphAdd(, F);
  2728                                         current +=1;
  2717                                         current +=1;
  2729                                         break;
  2718                                         break;
  2730                                 }
  2719                                 }
  2731 
  2720 
  2739 
  2728 
  2740                                 //else skip it
  2729                                 //else skip it
  2741                                 current +=1;
  2730                                 current +=1;
  2742                                 break;
  2731                                 break;
  2743 "
  2732 "
  2744 	| word nextLetter |
  2733         | word nextLetter |
  2745 	((word := self inputKey copyFrom: self currentIndex to: (self currentIndex + 1 min: self inputKey size)) = 'WR')
  2734         ((word := self inputKey copyFrom: currentIndex to: (currentIndex + 1 min: self inputKey size)) = 'WR')
  2746 	ifTrue: [
  2735         ifTrue: [
  2747 		self addPrimaryTranslation: 'R';
  2736                 self addPrimaryTranslation: 'R';
  2748 		addSecondaryTranslation: 'R'.
  2737                 addSecondaryTranslation: 'R'.
  2749 		^self incrementSkipCount: 1
  2738                 ^self incrementSkipCount: 1
  2750 	].
  2739         ].
  2751 	((self currentIndex = 1 and: [(nextLetter := self keyAt: self currentIndex + 1) isVowel]) or: [
  2740         ((currentIndex = 1 and: [(nextLetter := self keyAt: currentIndex + 1) isVowel]) or: [
  2752 		word = 'WH'
  2741                 word = 'WH'
  2753 	])
  2742         ])
  2754 	ifTrue: [
  2743         ifTrue: [
  2755 		nextLetter isVowel
  2744                 nextLetter isVowel
  2756 		ifTrue: [
  2745                 ifTrue: [
  2757 			self addPrimaryTranslation: 'A';
  2746                         self addPrimaryTranslation: 'A';
  2758 			addSecondaryTranslation: 'F'.
  2747                         addSecondaryTranslation: 'F'.
  2759 		] ifFalse: [
  2748                 ] ifFalse: [
  2760 			self addPrimaryTranslation: 'A';
  2749                         self addPrimaryTranslation: 'A';
  2761 			addSecondaryTranslation: 'A'.
  2750                         addSecondaryTranslation: 'A'.
  2762 		]
  2751                 ]
  2763 	].
  2752         ].
  2764 	((((self currentIndex = self inputKey size) and: [(self keyAt: self currentIndex - 1) isVowel])
  2753         ((((currentIndex = self inputKey size) and: [(self keyAt: currentIndex - 1) isVowel])
  2765 		or: [#('EWSKI' 'EWSKY' 'OWSKI' 'OWSKY') includes: (self inputKey copyFrom: ((self currentIndex - 1) max: 1) to: (self currentIndex + 3 min: self inputKey size))])
  2754                 or: [#('EWSKI' 'EWSKY' 'OWSKI' 'OWSKY') includes: (self inputKey copyFrom: ((currentIndex - 1) max: 1) to: (currentIndex + 3 min: self inputKey size))])
  2766 			or: [(self inputKey copyFrom: 1 to: 3) = 'SCH'])
  2755                         or: [(self inputKey copyFrom: 1 to: 3) = 'SCH'])
  2767 	ifTrue: [
  2756         ifTrue: [
  2768 		self addPrimaryTranslation: '';
  2757                 self addPrimaryTranslation: '';
  2769 		addSecondaryTranslation: 'F'.
  2758                 addSecondaryTranslation: 'F'.
  2770 		^self.
  2759                 ^self.
  2771 	].
  2760         ].
  2772 	(#('WICZ' 'WITZ') includes: (self inputKey copyFrom: self currentIndex to: (self currentIndex + 4 min: self inputKey size)))
  2761         (#('WICZ' 'WITZ') includes: (self inputKey copyFrom: currentIndex to: (currentIndex + 4 min: self inputKey size)))
  2773 	ifTrue: [
  2762         ifTrue: [
  2774 		self addPrimaryTranslation: 'TS';
  2763                 self addPrimaryTranslation: 'TS';
  2775 		addSecondaryTranslation: 'FX'.
  2764                 addSecondaryTranslation: 'FX'.
  2776 		^self incrementSkipCount: 3
  2765                 ^self incrementSkipCount: 3
  2777 	].
  2766         ].
  2778 !
  2767 !
  2779 
  2768 
  2780 processX
  2769 processX
  2781 	"http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2770         "http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2782 	case 'X':
  2771         case 'X':
  2783                                 //french e.g. breaux
  2772                                 //french e.g. breaux
  2784                                 if(!!((current == last) 
  2773                                 if(!!((current == last) 
  2785                                         AND (StringAt((current - 3), 3, IAU, EAU, ) 
  2774                                         AND (StringAt((current - 3), 3, IAU, EAU, ) 
  2786                                                         OR StringAt((current - 2), 2, AU, OU, ))) )
  2775                                                         OR StringAt((current - 2), 2, AU, OU, ))) )
  2787                                         MetaphAdd(KS);
  2776                                         MetaphAdd(KS);
  2792                                         current += 1;
  2781                                         current += 1;
  2793                                 break;
  2782                                 break;
  2794 "
  2783 "
  2795 
  2784 
  2796 
  2785 
  2797 	((self currentIndex = self inputKey size) and: [(#('IAU' 'EAU') includes: (self inputKey copyFrom: ((self currentIndex - 3) min: 1) to: self currentIndex)) or: [(#('AU' 'OU') includes: (self inputKey copyFrom: ((self currentIndex - 2) min: 1) to: self currentIndex))]]) not
  2786         ((currentIndex = self inputKey size) and: [(#('IAU' 'EAU') includes: (self inputKey copyFrom: ((currentIndex - 3) min: 1) to: currentIndex)) or: [(#('AU' 'OU') includes: (self inputKey copyFrom: ((currentIndex - 2) min: 1) to: currentIndex))]]) not
  2798 	ifTrue: [
  2787         ifTrue: [
  2799 		self addPrimaryTranslation: 'KS';
  2788                 self addPrimaryTranslation: 'KS';
  2800 		addSecondaryTranslation: 'KS'.
  2789                 addSecondaryTranslation: 'KS'.
  2801 	].
  2790         ].
  2802 	(#($C $X) includes: (self keyAt: self currentIndex + 1))
  2791         (#($C $X) includes: (self keyAt: currentIndex + 1))
  2803 	ifTrue: [
  2792         ifTrue: [
  2804 		^self incrementSkipCount: 1
  2793                 ^self incrementSkipCount: 1
  2805 	]
  2794         ]
  2806 		
       
  2807 	
       
  2808 !
  2795 !
  2809 
  2796 
  2810 processZ
  2797 processZ
  2811 	"http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2798         "http://aspell.sourceforge.net/metaphone/dmetaph.cpp
  2812 	case 'Z':
  2799         case 'Z':
  2813                                 //chinese pinyin e.g. 'zhao'
  2800                                 //chinese pinyin e.g. 'zhao'
  2814                                 if(GetAt(current + 1) == 'H')
  2801                                 if(GetAt(current + 1) == 'H')
  2815                                 {
  2802                                 {
  2816                                         MetaphAdd(J);
  2803                                         MetaphAdd(J);
  2817                                         current += 2;
  2804                                         current += 2;
  2830                                 else
  2817                                 else
  2831                                         current += 1;
  2818                                         current += 1;
  2832                                 break;
  2819                                 break;
  2833 "
  2820 "
  2834 
  2821 
  2835 	(self keyAt: self currentIndex + 1) = $H
  2822         (self keyAt: currentIndex + 1) = $H
  2836 	ifTrue: [
  2823         ifTrue: [
  2837 		self addPrimaryTranslation: 'J';
  2824                 self addPrimaryTranslation: 'J';
  2838 		addSecondaryTranslation: 'J'.
  2825                 addSecondaryTranslation: 'J'.
  2839 		^self incrementSkipCount: 1
  2826                 ^self incrementSkipCount: 1
  2840 	] ifFalse: [
  2827         ] ifFalse: [
  2841 		((#('ZO' 'ZI' 'ZA') includes: (self inputKey copyFrom: ((self currentIndex + 1) min: self inputKey size) to: ((self currentIndex + 2) min: self inputKey size))) or: [
  2828                 ((#('ZO' 'ZI' 'ZA') includes: (self inputKey copyFrom: ((currentIndex + 1) min: self inputKey size) to: ((currentIndex + 2) min: self inputKey size))) or: [
  2842 			(self isSlavoGermanic: self inputKey) and: [(self currentIndex > 1 and: [(self keyAt: self currentIndex - 1) ~= 'T'])]
  2829                         (self isSlavoGermanic: self inputKey) and: [(currentIndex > 1 and: [(self keyAt: currentIndex - 1) ~= 'T'])]
  2843 		])
  2830                 ])
  2844 		ifTrue: [
  2831                 ifTrue: [
  2845 			self addPrimaryTranslation: 'S';
  2832                         self addPrimaryTranslation: 'S';
  2846 			addSecondaryTranslation: 'TS'.
  2833                         addSecondaryTranslation: 'TS'.
  2847 		] ifFalse: [
  2834                 ] ifFalse: [
  2848 			self addPrimaryTranslation: 'S';
  2835                         self addPrimaryTranslation: 'S';
  2849 			addSecondaryTranslation: 'S'.
  2836                         addSecondaryTranslation: 'S'.
  2850 		].
  2837                 ].
  2851 		(self keyAt: self currentIndex + 1) = $Z
  2838                 (self keyAt: currentIndex + 1) = $Z
  2852 		ifTrue: [
  2839                 ifTrue: [
  2853 			^self incrementSkipCount: 1
  2840                         ^self incrementSkipCount: 1
  2854 		].
  2841                 ].
  2855 	]
  2842         ]
  2856 		
       
  2857 	
       
  2858 ! !
  2843 ! !
  2859 
  2844 
  2860 !PhoneticStringUtilities::MiracodeStringComparator class methodsFor:'documentation'!
  2845 !PhoneticStringUtilities::MiracodeStringComparator class methodsFor:'documentation'!
  2861 
  2846 
  2862 documentation
  2847 documentation
  2900 ! !
  2885 ! !
  2901 
  2886 
  2902 !PhoneticStringUtilities class methodsFor:'documentation'!
  2887 !PhoneticStringUtilities class methodsFor:'documentation'!
  2903 
  2888 
  2904 version
  2889 version
  2905     ^ '$Header: /cvs/stx/stx/libbasic2/PhoneticStringUtilities.st,v 1.6 2009-08-12 18:26:40 cg Exp $'
  2890     ^ '$Header: /cvs/stx/stx/libbasic2/PhoneticStringUtilities.st,v 1.7 2009-08-16 10:02:50 cg Exp $'
  2906 ! !
  2891 ! !