From 420ea7200636d07ddca643d37a5fa9554401cd44 Mon Sep 17 00:00:00 2001
From: magnum <magnum>
Date: Tue, 16 Aug 2011 09:40:17 +0200
Subject: [PATCH 15/16] Add best-effort vowel matching to cmpt_cp.pl and JtR

---
 run/cmpt_cp.pl      |   38 +++++++++++++++++++++++++++++++++++---
 src/encoding_data.h |   37 +++++++++++++++++++++++++++++++++++++
 src/rules.c         |   28 ++++++++++++++++++++++++++--
 3 files changed, 98 insertions(+), 5 deletions(-)

diff --git a/run/cmpt_cp.pl b/run/cmpt_cp.pl
index f5d077e..f626d7d 100755
--- a/run/cmpt_cp.pl
+++ b/run/cmpt_cp.pl
@@ -2,6 +2,8 @@
 use strict;
 use Encode;
 use Switch;
+use Unicode::Normalize;
+use utf8;  # This source file must be stored UTF-8 encoded
 
 ###############################################################################
 # code page data builder, by magnum / JimF.   v1.2
@@ -44,8 +46,8 @@ sub lookupCategory {
 }
 
 my $to_unicode_high128="";
-my $lower="";  my $upper="";  my $lowonly="";  my $uponly="";  my $specials = "";  my $punctuation = "";  my $alpha = "";  my $digits = "";  my $control = "";  my $invalid = ""; my $whitespace = "";
-my $clower=""; my $cupper=""; my $clowonly=""; my $cuponly=""; my $cspecials = ""; my $cpunctuation = ""; my $calpha = ""; my $cdigits = "";
+my $lower="";  my $upper="";  my $lowonly="";  my $uponly="";  my $specials = "";  my $punctuation = "";  my $alpha = "";  my $digits = "";  my $control = "";  my $invalid = ""; my $whitespace = ""; my $vowels = ""; my $consonants = "";
+my $clower=""; my $cupper=""; my $clowonly=""; my $cuponly=""; my $cspecials = ""; my $cpunctuation = ""; my $calpha = ""; my $cdigits = ""; my $cvowels = ""; my $cconsonants = "";
 my $encu = uc($enc);my $hs = "";
 $encu =~ s/-/_/g;
 #######################################
@@ -119,7 +121,25 @@ foreach my $i (0x80..0xFF) {
 		my $cat = lookupCategory(ord($c));
 		switch ($cat) {
 			case /^Cf/ { $specials .= sprintf("\\x%02X", $i); $cspecials .= $c }
-			case /^L[lotu]/ { $alpha .= sprintf("\\x%02X", $i); $calpha .= $c }
+			case /^L[lotu]/ {
+				$alpha .= sprintf("\\x%02X", $i);
+				$calpha .= $c;
+
+				# best-effort vowel/consonant matching
+				# Note eg. in English, y and w CAN be vowels depending on
+				# situation (boy, yet, we)
+
+				# We normalize to decomposed and match known vowels in lc
+				my $nfd = substr(NFD($c), 0, 1);
+				# Done: Latin, Nordic, Greek, Russian, Ukrainian, Turkish
+				if ($nfd =~ m/[aoueiœæøɪʏɛɔαεηιοωυаэыуояеюиєіı]/i) {
+					$vowels .= sprintf("\\x%02X", ord($c));
+					$cvowels .= $c;
+				} else {
+					$consonants .= sprintf("\\x%02X", ord($c));
+					$cconsonants .= $c;
+				}
+			}
 			case /^Lm/ { $specials .= sprintf("\\x%02X", $i); $cspecials .= $c }
 			#case /^Ll/ { $lower .= sprintf("\\x%02X", $i); }
 			#case /^L[tu]/ { $upper .= sprintf("\\x%02X", $i); }
@@ -193,6 +213,18 @@ if (length($control)>80) {print"\\\n\t";}
 if (length($control)>0)  {print "\"".$control."\"";}
 print "\n";
 
+print "\n// $cvowels\n" if $verbose;
+print "#define CHARS_VOWELS_".$encu." ";
+if (length($vowels)>80) {print"\\\n\t";}
+if (length($vowels)>0)  {print "\"".$vowels."\"";}
+print "\n";
+
+print "\n// $cconsonants\n" if $verbose;
+print "#define CHARS_CONSONANTS_".$encu." ";
+if (length($consonants)>80) {print"\\\n\t";}
+if (length($consonants)>0)  {print "\"".$consonants."\"";}
+print "\n";
+
 print "\n" if $verbose;
 print "#define CHARS_INVALID_".$encu." ";
 if (length($invalid)>80) {print"\\\n\t";}
diff --git a/src/encoding_data.h b/src/encoding_data.h
index b30fd7d..5a47332 100644
--- a/src/encoding_data.h
+++ b/src/encoding_data.h
@@ -55,6 +55,9 @@ static UTF16 ISO_8859_1_to_unicode_high128[] = {
 #define CHARS_WHITESPACE_ISO_8859_1 "\xA0"
 #define CHARS_CONTROL_ISO_8859_1 \
 	"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
+#define CHARS_VOWELS_ISO_8859_1 \
+	"\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD2\xD3\xD4\xD5\xD6\xD8\xD9\xDA\xDB\xDC\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF2\xF3\xF4\xF5\xF6\xF8\xF9\xFA\xFB\xFC"
+#define CHARS_CONSONANTS_ISO_8859_1 "\xAA\xB5\xBA\xC7\xD0\xD1\xDD\xDE\xDF\xE7\xF0\xF1\xFD\xFE\xFF"
 #define CHARS_INVALID_ISO_8859_1 ""
 
 // here is the KOI8_R to Unicode conversion for KOI8_R characters from 0x80 to 0xFF
@@ -81,6 +84,10 @@ static UTF16 KOI8_R_to_unicode_high128[] = {
 	"\xA3\xB3\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"
 #define CHARS_WHITESPACE_KOI8_R "\x9A"
 #define CHARS_CONTROL_KOI8_R
+#define CHARS_VOWELS_KOI8R \
+	"\x451\x401\x44E\x430\x435\x438\x439\x43E\x44F\x443\x44B\x44D\x42E\x410\x415\x418\x419\x41E\x42F\x423\x42B\x42D"
+#define CHARS_CONSONANTS_KOI8R \
+	"\x431\x446\x434\x444\x433\x445\x43A\x43B\x43C\x43D\x43F\x440\x441\x442\x436\x432\x44C\x437\x448\x449\x447\x44A\x411\x426\x414\x424\x413\x425\x41A\x41B\x41C\x41D\x41F\x420\x421\x422\x416\x412\x42C\x417\x428\x429\x427\x42A"
 #define CHARS_INVALID_KOI8_R ""
 
 // here is the CP1251 to Unicode conversion for CP1251 characters from 0xA0 to 0xFF 
@@ -106,6 +113,10 @@ static UTF16 CP1251_to_unicode_high128[] = {
 	"\x80\x81\x83\x8A\x8C\x8D\x8E\x8F\x90\x9A\x9C\x9D\x9E\x9F\xA1\xA2\xA3\xA5\xA8\xAA\xAF\xB2\xB3\xB4\xB5\xB8\xBA\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"
 #define CHARS_WHITESPACE_CP1251 "\xA0"
 #define CHARS_CONTROL_CP1251
+#define CHARS_VOWELS_CP1251 \
+	"\x40E\x45E\x401\x404\x407\x406\x456\x451\x454\x457\x410\x415\x418\x419\x41E\x423\x42B\x42D\x42E\x42F\x430\x435\x438\x439\x43E\x443\x44B\x44D\x44E\x44F"
+#define CHARS_CONSONANTS_CP1251 \
+	"\x402\x403\x453\x409\x40A\x40C\x40B\x40F\x452\x459\x45A\x45C\x45B\x45F\x408\x490\x491\xB5\x458\x405\x455\x411\x412\x413\x414\x416\x417\x41A\x41B\x41C\x41D\x41F\x420\x421\x422\x424\x425\x426\x427\x428\x429\x42A\x42C\x431\x432\x433\x434\x436\x437\x43A\x43B\x43C\x43D\x43F\x440\x441\x442\x444\x445\x446\x447\x448\x449\x44A\x44C"
 #define CHARS_INVALID_CP1251 "\x98"
 
 // here is the CP866 to Unicode conversion for CP866 characters from 0xA0 to 0xFF
@@ -132,6 +143,10 @@ static UTF16 CP866_to_unicode_high128[] = {
 	"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7"
 #define CHARS_WHITESPACE_CP866 "\xFF"
 #define CHARS_CONTROL_CP866
+#define CHARS_VOWELS_CP866 \
+	"\x410\x415\x418\x419\x41E\x423\x42B\x42D\x42E\x42F\x430\x435\x438\x439\x43E\x443\x44B\x44D\x44E\x44F\x401\x451\x404\x454\x407\x457\x40E\x45E"
+#define CHARS_CONSONANTS_CP866 \
+	"\x411\x412\x413\x414\x416\x417\x41A\x41B\x41C\x41D\x41F\x420\x421\x422\x424\x425\x426\x427\x428\x429\x42A\x42C\x431\x432\x433\x434\x436\x437\x43A\x43B\x43C\x43D\x43F\x440\x441\x442\x444\x445\x446\x447\x448\x449\x44A\x44C"
 #define CHARS_INVALID_CP866 ""
 
 // here is the CP1252 to Unicode conversion for CP1252 characters from 0xA0 to 0xFF
@@ -159,6 +174,10 @@ static UTF16 CP1252_to_unicode_high128[] = {
 	"\x83\x8A\x8C\x8E\x9A\x9C\x9E\x9F\xAA\xB5\xBA\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"
 #define CHARS_WHITESPACE_CP1252 "\xA0"
 #define CHARS_CONTROL_CP1252
+#define CHARS_VOWELS_CP1252 \
+	"\x152\x153\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD2\xD3\xD4\xD5\xD6\xD8\xD9\xDA\xDB\xDC\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF2\xF3\xF4\xF5\xF6\xF8\xF9\xFA\xFB\xFC"
+#define CHARS_CONSONANTS_CP1252 \
+	"\x192\x160\x17D\x161\x17E\x178\xAA\xB5\xBA\xC7\xD0\xD1\xDD\xDE\xDF\xE7\xF0\xF1\xFD\xFE\xFF"
 #define CHARS_INVALID_CP1252 "\x81\x8D\x8F\x90\x9D"
 
 // here is the ISO_8859_15 to Unicode conversion for ISO_8859_15 characters from 0xA0 to 0xFF
@@ -186,6 +205,10 @@ static UTF16 ISO_8859_15_to_unicode_high128[] = {
 #define CHARS_WHITESPACE_ISO_8859_15 "\xA0"
 #define CHARS_CONTROL_ISO_8859_15 \
 	"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
+#define CHARS_VOWELS_ISO_8859_15 \
+	"\x152\x153\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD2\xD3\xD4\xD5\xD6\xD8\xD9\xDA\xDB\xDC\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF2\xF3\xF4\xF5\xF6\xF8\xF9\xFA\xFB\xFC"
+#define CHARS_CONSONANTS_ISO_8859_15 \
+	"\x160\x161\xAA\x17D\xB5\x17E\xBA\x178\xC7\xD0\xD1\xDD\xDE\xDF\xE7\xF0\xF1\xFD\xFE\xFF"
 #define CHARS_INVALID_ISO_8859_15 ""
 
 // here is the CP437 to Unicode conversion for CP437 characters from 0xA0 to 0xFF
@@ -212,6 +235,10 @@ static UTF16 CP437_to_unicode_high128[] = {
 	"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xED\xEE"
 #define CHARS_WHITESPACE_CP437 "\xFF"
 #define CHARS_CONTROL_CP437
+#define CHARS_VOWELS_CP437 \
+	"\xFC\xE9\xE2\xE4\xE0\xE5\xEA\xEB\xE8\xEF\xEE\xEC\xC4\xC5\xC9\xE6\xC6\xF4\xF6\xF2\xFB\xF9\xD6\xDC\xE1\xED\xF3\xFA\x3B1\x3A9\x3B5"
+#define CHARS_CONSONANTS_CP437 \
+	"\xC7\xE7\xFF\x192\xF1\xD1\xAA\xBA\xDF\x393\x3C0\x3A3\x3C3\xB5\x3C4\x3A6\x398\x3B4\x3C6"
 #define CHARS_INVALID_CP437 ""
 
 // here is the CP850 to Unicode conversion for CP850 characters from 0xA0 to 0xFF
@@ -240,6 +267,9 @@ static UTF16 CP850_to_unicode_high128[] = {
 	"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9D\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xB5\xB6\xB7\xC6\xC7\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xDE\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED"
 #define CHARS_WHITESPACE_CP850 "\xFF"
 #define CHARS_CONTROL_CP850
+#define CHARS_VOWELS_CP850 \
+	"\xFC\xE9\xE2\xE4\xE0\xE5\xEA\xEB\xE8\xEF\xEE\xEC\xC4\xC5\xC9\xE6\xC6\xF4\xF6\xF2\xFB\xF9\xD6\xDC\xF8\xD8\xE1\xED\xF3\xFA\xC1\xC2\xC0\xE3\xC3\xCA\xCB\xC8\x131\xCD\xCE\xCF\xCC\xD3\xD4\xD2\xF5\xD5\xDA\xDB\xD9"
+#define CHARS_CONSONANTS_CP850 "\xC7\xE7\xFF\x192\xF1\xD1\xAA\xBA\xF0\xD0\xDF\xB5\xFE\xDE\xFD\xDD"
 #define CHARS_INVALID_CP850 ""
 
 // here is the CP858 to Unicode conversion for CP858 characters from 0xA0 to 0xFF
@@ -267,6 +297,9 @@ static UTF16 CP858_to_unicode_high128[] = {
 	"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9D\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xB5\xB6\xB7\xC6\xC7\xD0\xD1\xD2\xD3\xD4\xD6\xD7\xD8\xDE\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED"
 #define CHARS_WHITESPACE_CP858 "\xFF"
 #define CHARS_CONTROL_CP858
+#define CHARS_VOWELS_CP858 \
+	"\xFC\xE9\xE2\xE4\xE0\xE5\xEA\xEB\xE8\xEF\xEE\xEC\xC4\xC5\xC9\xE6\xC6\xF4\xF6\xF2\xFB\xF9\xD6\xDC\xF8\xD8\xE1\xED\xF3\xFA\xC1\xC2\xC0\xE3\xC3\xCA\xCB\xC8\xCD\xCE\xCF\xCC\xD3\xD4\xD2\xF5\xD5\xDA\xDB\xD9"
+#define CHARS_CONSONANTS_CP858 "\xC7\xE7\xFF\x192\xF1\xD1\xAA\xBA\xF0\xD0\xDF\xB5\xFE\xDE\xFD\xDD"
 #define CHARS_INVALID_CP858 ""
 
 // here is the CP737 to Unicode conversion for CP737 characters from 0xA0 to 0xFF
@@ -293,6 +326,10 @@ static UTF16 CP737_to_unicode_high128[] = {
 	"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF4\xF5"
 #define CHARS_WHITESPACE_CP737 "\xFF"
 #define CHARS_CONTROL_CP737
+#define CHARS_VOWELS_CP737 \
+	"\x391\x395\x397\x399\x39F\x3A5\x3A9\x3B1\x3B5\x3B7\x3B9\x3BF\x3C5\x3C9\x3AC\x3AD\x3AE\x3CA\x3AF\x3CC\x3CD\x3CB\x3CE\x386\x388\x389\x38A\x38C\x38E\x38F\x3AA\x3AB"
+#define CHARS_CONSONANTS_CP737 \
+	"\x392\x393\x394\x396\x398\x39A\x39B\x39C\x39D\x39E\x3A0\x3A1\x3A3\x3A4\x3A6\x3A7\x3A8\x3B2\x3B3\x3B4\x3B6\x3B8\x3BA\x3BB\x3BC\x3BD\x3BE\x3C0\x3C1\x3C3\x3C2\x3C4\x3C6\x3C7\x3C8"
 #define CHARS_INVALID_CP737 ""
 
 #endif // __ENCODING_DATA_H__
diff --git a/src/rules.c b/src/rules.c
index 63a620f..62c0d64 100644
--- a/src/rules.c
+++ b/src/rules.c
@@ -92,6 +92,10 @@ static struct {
 	"``1234567890-=qqwertyuiop[aasdfghjkl;zzxcvbnm,." \
 	"~~!@#$%^&*()_+QQWERTYUIOP{AASDFGHJKL:ZZXCVBNM<>"
 
+#define CHARS_VOWELS \
+	"aeiouAEIOU"
+#define CHARS_CONSONANTS \
+	"bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ"
 #define CHARS_LOWER \
 	"abcdefghijklmnopqrstuvwxyz"
 #define CHARS_UPPER \
@@ -284,8 +288,6 @@ static void rules_init_classes(void)
 	eightbitchars[128] = 0;
 
 	rules_init_class('?', "?");
-	rules_init_class('v', "aeiouAEIOU");
-	rules_init_class('c', "bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ");
 	rules_init_class('b', (char *)&eightbitchars);
 	rules_init_class('Z', "");
 
@@ -306,6 +308,8 @@ static void rules_init_classes(void)
 	}
 
 	if (options.iso8859_1) {
+		rules_init_class('v', CHARS_VOWELS CHARS_VOWELS_ISO_8859_1);
+		rules_init_class('c', CHARS_CONSONANTS CHARS_CONSONANTS_ISO_8859_1);
 		rules_init_class('w', CHARS_WHITESPACE CHARS_WHITESPACE_ISO_8859_1);
 		rules_init_class('p', CHARS_PUNCTUATION CHARS_PUNCTUATION_ISO_8859_1);
 		rules_init_class('s', CHARS_SPECIALS CHARS_SPECIALS_ISO_8859_1);
@@ -317,6 +321,8 @@ static void rules_init_classes(void)
 		rules_init_class('o', CHARS_CONTROL_ASCII CHARS_CONTROL_ISO_8859_1);
 		rules_init_class('Y', CHARS_INVALID_ISO_8859_1);
 	} else if (options.koi8_r) {
+		rules_init_class('v', CHARS_VOWELS CHARS_VOWELS_KOI8_R);
+		rules_init_class('c', CHARS_CONSONANTS CHARS_CONSONANTS_KOI8_R);
 		rules_init_class('w', CHARS_WHITESPACE CHARS_WHITESPACE_KOI8_R);
 		rules_init_class('p', CHARS_PUNCTUATION CHARS_PUNCTUATION_KOI8_R);
 		rules_init_class('s', CHARS_SPECIALS CHARS_SPECIALS_KOI8_R);
@@ -328,6 +334,8 @@ static void rules_init_classes(void)
 		rules_init_class('o', CHARS_CONTROL_ASCII CHARS_CONTROL_KOI8_R);
 		rules_init_class('Y', CHARS_INVALID_KOI8_R);
 	} else if (options.cp1251) {
+		rules_init_class('v', CHARS_VOWELS CHARS_VOWELS_CP1251);
+		rules_init_class('c', CHARS_CONSONANTS CHARS_CONSONANTS_CP1251);
 		rules_init_class('w', CHARS_WHITESPACE CHARS_WHITESPACE_CP1251);
 		rules_init_class('p', CHARS_PUNCTUATION CHARS_PUNCTUATION_CP1251);
 		rules_init_class('s', CHARS_SPECIALS CHARS_SPECIALS_CP1251);
@@ -339,6 +347,8 @@ static void rules_init_classes(void)
 		rules_init_class('o', CHARS_CONTROL_ASCII CHARS_CONTROL_CP1251);
 		rules_init_class('Y', CHARS_INVALID_CP1251);
 	} else if (options.cp866) {
+		rules_init_class('v', CHARS_VOWELS CHARS_VOWELS_CP866);
+		rules_init_class('c', CHARS_CONSONANTS CHARS_CONSONANTS_CP866);
 		rules_init_class('w', CHARS_WHITESPACE CHARS_WHITESPACE_CP866);
 		rules_init_class('p', CHARS_PUNCTUATION CHARS_PUNCTUATION_CP866);
 		rules_init_class('s', CHARS_SPECIALS CHARS_SPECIALS_CP866);
@@ -350,6 +360,8 @@ static void rules_init_classes(void)
 		rules_init_class('o', CHARS_CONTROL_ASCII CHARS_CONTROL_CP866);
 		rules_init_class('Y', CHARS_INVALID_CP866);
 	} else if (options.cp1252) {
+		rules_init_class('v', CHARS_VOWELS CHARS_VOWELS_CP1252);
+		rules_init_class('c', CHARS_CONSONANTS CHARS_CONSONANTS_CP1252);
 		rules_init_class('w', CHARS_WHITESPACE CHARS_WHITESPACE_CP1252);
 		rules_init_class('p', CHARS_PUNCTUATION CHARS_PUNCTUATION_CP1252);
 		rules_init_class('s', CHARS_SPECIALS CHARS_SPECIALS_CP1252);
@@ -361,6 +373,8 @@ static void rules_init_classes(void)
 		rules_init_class('o', CHARS_CONTROL_ASCII CHARS_CONTROL_CP1252);
 		rules_init_class('Y', CHARS_INVALID_CP1252);
 	} else if (options.iso8859_15) {
+		rules_init_class('v', CHARS_VOWELS CHARS_VOWELS_ISO_8859_15);
+		rules_init_class('c', CHARS_CONSONANTS CHARS_CONSONANTS_ISO_8859_15);
 		rules_init_class('w', CHARS_WHITESPACE CHARS_WHITESPACE_ISO_8859_15);
 		rules_init_class('p', CHARS_PUNCTUATION CHARS_PUNCTUATION_ISO_8859_15);
 		rules_init_class('s', CHARS_SPECIALS CHARS_SPECIALS_ISO_8859_15);
@@ -372,6 +386,8 @@ static void rules_init_classes(void)
 		rules_init_class('o', CHARS_CONTROL_ASCII CHARS_CONTROL_ISO_8859_15);
 		rules_init_class('Y', CHARS_INVALID_ISO_8859_15);
 	} else if (options.cp437) {
+		rules_init_class('v', CHARS_VOWELS CHARS_VOWELS_CP437);
+		rules_init_class('c', CHARS_CONSONANTS CHARS_CONSONANTS_CP437);
 		rules_init_class('w', CHARS_WHITESPACE CHARS_WHITESPACE_CP437);
 		rules_init_class('p', CHARS_PUNCTUATION CHARS_PUNCTUATION_CP437);
 		rules_init_class('s', CHARS_SPECIALS CHARS_SPECIALS_CP437);
@@ -384,6 +400,8 @@ static void rules_init_classes(void)
 		rules_init_class('Y', CHARS_INVALID_CP437);
 	} else if (options.cp850) {
 		// NOTE, we need to deal with U+0131 (dottless I)
+		rules_init_class('v', CHARS_VOWELS CHARS_VOWELS_CP850);
+		rules_init_class('c', CHARS_CONSONANTS CHARS_CONSONANTS_CP850);
 		rules_init_class('w', CHARS_WHITESPACE CHARS_WHITESPACE_CP850);
 		rules_init_class('p', CHARS_PUNCTUATION CHARS_PUNCTUATION_CP850);
 		rules_init_class('s', CHARS_SPECIALS CHARS_SPECIALS_CP850);
@@ -395,6 +413,8 @@ static void rules_init_classes(void)
 		rules_init_class('o', CHARS_CONTROL_ASCII CHARS_CONTROL_CP850);
 		rules_init_class('Y', CHARS_INVALID_CP850);
 	} else if (options.cp858) {
+		rules_init_class('v', CHARS_VOWELS CHARS_VOWELS_CP858);
+		rules_init_class('c', CHARS_CONSONANTS CHARS_CONSONANTS_CP858);
 		rules_init_class('w', CHARS_WHITESPACE CHARS_WHITESPACE_CP858);
 		rules_init_class('p', CHARS_PUNCTUATION CHARS_PUNCTUATION_CP858);
 		rules_init_class('s', CHARS_SPECIALS CHARS_SPECIALS_CP858);
@@ -406,6 +426,8 @@ static void rules_init_classes(void)
 		rules_init_class('o', CHARS_CONTROL_ASCII CHARS_CONTROL_CP858);
 		rules_init_class('Y', CHARS_INVALID_CP858);
 	} else if (options.cp737) {
+		rules_init_class('v', CHARS_VOWELS CHARS_VOWELS_CP737);
+		rules_init_class('c', CHARS_CONSONANTS CHARS_CONSONANTS_CP737);
 		rules_init_class('w', CHARS_WHITESPACE CHARS_WHITESPACE_CP737);
 		rules_init_class('p', CHARS_PUNCTUATION CHARS_PUNCTUATION_CP737);
 		rules_init_class('s', CHARS_SPECIALS CHARS_SPECIALS_CP737);
@@ -417,6 +439,8 @@ static void rules_init_classes(void)
 		rules_init_class('o', CHARS_CONTROL_ASCII CHARS_CONTROL_CP737);
 		rules_init_class('Y', CHARS_INVALID_CP737);
 	} else {
+		rules_init_class('v', CHARS_VOWELS);
+		rules_init_class('c', CHARS_CONSONANTS);
 		rules_init_class('w', CHARS_WHITESPACE);
 		rules_init_class('p', CHARS_PUNCTUATION);
 		rules_init_class('s', CHARS_SPECIALS);
-- 
1.7.4.1

