#! /usr/bin/perl

#
# Copyright 2006 Luciano Montanaro
#

#   This file is free software; you can redistribute it and/or
#   modify it under the terms of the GNU Library General Public
#   License as published by the Free Software Foundation; either
#   version 2 of the License, or (at your option) any later version.

#   This library is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#   Library General Public License for more details.

#   You should have received a copy of the GNU Library General Public License
#   along with this library; see the file COPYING.LIB.  If not, write to
#   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
#   Boston, MA 02110-1301, USA.

use Getopt::Std;
use Text::Aspell;

# Spelling check 
my $speller = Text::Aspell->new or die;

$speller->set_option('lang','it');
#print $speller->list_dictionaries;
     
my $verbose = 0;
my $check = 0;
my $line = 0;
my $lasterrorline = -1;
my $text;

if (!getopts('wp')) {
	print STDERR ("Sintassi sconosciuta sulla riga di comando.\n");
	printUsage();
	exit;
} 

my $source = $ARGV[0];
if (defined($source)) {
	open STDIN, "$source" or die "Cannot open input file";
}

my %unknownWords;

my %gender = (
	'artista' => 'm',
	'automa' => 'm',
	'autoradio' => 'f',
	'cinema' => 'm',
	'clima' => 'm',
	'collega' => 'm',
	'contro' => 'f',
	'diagramma' => 'm',
	'foto' => 'f',
	'fotogramma' => 'm',
	'istogramma' => 'm',
	'mano' => 'f',
	'macro' => 'f',
	'meta' => 'm',
	'panorama' => 'm',
	'parallelogramma' => 'm',
	'pianeta' => 'm',
	'pirata' => 'm',
	'poeta' => 'm',
	'problema' => 'm',
	'progettista' => 'm',
	'programma' => 'm',
	'promemoria' => 'm',
	'sistema' => 'm',
	'sottoprogramma' => 'm',
	'sottosistema' => 'm',
	'tema' => 'm',
);

my %camelword = (
	'ASpell' => 't',
	'CImg' => 't',
	'CMake' => 't',
	'CTags' => 't',
	'CPU' => 't',
	'GBit' => 't',
	'GByte' => 't',
	'GHz' => 't',
	'GConf' => 't',
	'GPhoto' => 't',
	'GStreamer' => 't',
	'ICal' => 't',
	'ICalendar' => 't',
	'ICard' => 't',
	'ICCCM' => 't',
	'IFrame' => 't',
	'ISpell' => 't',
	'MBit' => 't',
	'MByte' => 't',
	'MHz' => 't',
	'MEncoder' => 't',
	'MPlayer' => 't',
	'NEdit' => 't',
	'OClock' => 't',
	'QApplication' => 't',
	'QBrush' => 't',
	'QColor' => 't',
	'QMake' => 't',
	'QPainter' => 't',
	'QPicture' => 't',
	'QRegExp' => 't',
	'QString' => 't',
	'QTextEdit' => 't',
	# 'QTopia' => 't', Qtopia should be written with only a capital Q
	'QWidget' => 't',
	'TByte' => 't',
	'VCal' => 't',
	'VCard' => 't',
	'XFree' => 't',
	'ZAngband' => 't',
	'ZLib' => 't',
	'ZModem' => 't',
);

my %abbreviation = (
	'cart' => 't',
	'dir' => 't',
	'dim' => 't',
	'dimens' => 't',
	'ecc' => 't',
	'es' => 't',
	'espr' => 't',
	'Inc' => 't',
	'incr' => 't',
	'Jr' => 't',
	'n' => 't',
	'ndt' => 't',
	'orizz' => 't',
	'val' => 't',
	'vert' => 't',
);

my %notruntogether = (
	'developer' => 't',
	'Developer' => 't',
	'email' => 't',
	'Email' => 't',
	'emoticon' => 't',
	'escputil' => 't',
	'gmail' => 't',
	'guiicon' => 't',
	'Jesper' => 't',
	'klipper' => 't',
	'kmail' => 't',
	'KMail' => 't',
	'mail' => 't',
	'Mail' => 't',
	'KMail' => 't',
	'procmail' => 't',
	'Procmail' => 't',
	'sendmail' => 't',
	'Sendmail' => 't',
	'super' => 't',
	'Super' => 't',
);

my %extension = (
	'com' => 't',
	'de' => 't',
	'fr' => 't',
	'ics' => 't',
	'it' => 't',
	'net' => 't',
	'org' => 't',
	'avi' => 't',
	'doc' => 't',
	'desktop' => 't',
	'directory' => 't',
	'dvi' => 't',
	'gif' => 't',
	'iso' => 't',
	'mp3' => 't',
	'mpg' => 't',
	'mpeg' => 't',
	'png' => 't',
	'ogg' => 't',
	'html' => 't',
	'kde' => 't',
	'kderc' => 't',
	'jpeg' => 't',
	'jpg' => 't',
	'prc' => 't',
	'pwm' => 't',
	'pwk' => 't',
	'txt' => 't',
	'vcs' => 't',
	'wav' => 't',
);

print STDERR ("Checking $source...\n") if ($verbose);

while (<STDIN>) {
	$line++;
	
	if (defined($opt_p)) {
		$check = 1;
	} else {
		if (/^#.*$/) {
			# discard comments
			next;
		} elsif (/^msgid/) {
			# discard message ids
			$check = 0;
			print STDERR ("msgid, not checking at line $line\n") if ($verbose > 1);
		} elsif (/^msgctxt/) {
			# discard message contexts too
			$check = 0;
			print STDERR ("msgctxt, not checking at line $line\n") if ($verbose > 1);
		} elsif (/^msgstr/) {
			# check msgstr
			$check = 1;
			print STDERR ("msgstr, checking at line $line\n") if ($verbose > 1);
		} elsif (
			/(X-Generator|Content-|POT-|Language-|Project-Id-|Report-Msgid-Bugs-To|X-KDE-DocBook-|Plural-Forms)/) {
			# discard special messages
			$check = 0;
		}
	}
	if ($check) {
		$text = $_;

		my $ft = filter_extra_chars($text);

		# Accumulate text in one string
		if (defined($opt_w)) {
			while (<IN>) {
				$line++;
				last if (/^$/);
				last if (/^#.*$/);
				$text .= $_;
				$ft .= filter_extra_chars($_);
			}
		}
		$ft =~ s/\n//g;
		
		check_che($ft);
		check_se($ft);
		check_ne($ft);
		check_po($ft);
		check_si($ft);
		check_triple($ft);
		check_commas($ft);
		check_spaces($ft);
		check_accents($ft);
		check_apostrophe($ft);
		check_qual($ft);
		check_repeated($ft);
		check_e($ft);
		check_capitals($ft);
		check_english_plural($ft);
		check_double_uppercase($ft);
		check_missing_uppercase($ft);
		check_title_case($ft);
		check_bad_phrases($ft);
		check_gender($ft);
		check_qu($ft);
		check_common_mistyping($ft);
		#check_ing($ft);
		check_conflict_marker($ft);
		check_runtogether_words($ft);
		check_aspell($ft);
		check_wesnoth($ft);
		check_ai($ft);
		check_salva_come($ft);
		if (defined($opt_o)) {
			# Do checks that work only on whole messages.
			# For example matching parenthesis, matching quotes etc.
		}
		# check_double_vowels($ft);
		# TODO
		#
	} else {
		next;
	}
}

exit 0;

sub error($)
{
	$message = shift;
	print "\n$text" if ($lasterrorline != $line);
	$lasterrorline = $line;
	print ("$source:$line - $message\n");
}

sub filter_extra_chars($)
{
	# Generic rules
	
	# Remove leding and trailing '"'
	s/^msgstr\s*"//;
	s/^\s*"//;
	s/"\s*$//;
	
	# Change '\"' to simply '"'
	s/\\"/"/g;

	# Change "\n" to a space
	s/\\[nt]/ /g;
	
	# Rules useful to strip KDE markup.
	
	# Convert common html/xml entities
	s/&lt;/</g;
	s/&gt;/>/g;
	s/&amp;/&/g;
	s/&aacute;/á/g;
	s/&agrave;/à/g;
	s/&Auml;/Ä/g;
	s/&auml;/ä/g;
	s/&ccedil;/ç/g;
	s/&eacute;/é/g;
	s/&egrave;/è/g;
	s/&iacute;/í/g;
	s/&igrave;/ì/g;
	s/&ograve;/ò/g;
	s/&mdash;/---/g;
	s/&ndash;/--/g;
	s/&ouml;/ö/g;
	s/&Ouml;/Ö/g;
	s/&szlig;/ß/g;
	s/&uacute;/ú/g;
	s/&ugrave;/ù/g;
	s/&uuml;/ü/g;
	s/&Uuml;/Ü/g;
	s/&lowbar;/_/g;
	s/&quot;/"/g;
	s/&nbsp;/ /g;
	s/&konqueror;/Konqueror/g; # Silence lots of warnings in the doc.
	s/&kmail;/KMail/g; # Silence lots of warnings in the doc.
	s/&amarok;/Amarok/g; # Silence lots of warnings in the doc.

	s/<[ib]>//; # remove html/qtxml italics indicator
	s/<\/[ib]>//; # remove html/qtxml italics indicator

	# Remove KDE accelerator indicator
	s/([a-z])&([a-z])/\1\2/ig;
	# Remove GNOME accelerator indicator
	s/([a-z])_([a-z])/\1\2/ig;

	return $_;
}

sub check_se($)
{
	my $message = shift;
	print STDERR ("$source:$line checking \"se\": $message\n") if ($verbose > 1);
	if ($message =~ /\bsè[\s\.!?]/i) {
		# Accented letters are not considered 'word' letters, so boundary check does not work.
		my $match = $&;
		if (!($message =~ /($match)[a-z]/i)) {
			error("accento su \"sé\" sbagliato");
		}
	}
	if ($message =~ /\b(a|di|da|in|con|su|per|tra|fra) se\b/i and
		!($message =~ /\bse stess[aio]\b/i) # se stesso è accettabile...
	) {
		error("controlla se è \"se\" o \"sé\"");
	}
}

sub check_ne($)
{
	my $message = shift;
	print STDERR ("$source:$line checking \"né\": $message\n") if ($verbose > 1);
	if ($message =~ /[^a-z]nè\s/i) {
		error("accento su \"né\" sbagliato");
	}
}

sub check_che($)
{
	my $message = shift;
	print STDERR ("$source:$line checking \"-ché\": $message\n") if ($verbose > 1);
	if ($message =~ /([a-z]*chè)/i) {
		error("accento su $1 sbagliato");
	}
}

sub check_po($)
{
	my $message = shift;
	print STDERR ("$source:$line checking \"po\": $message\n") if ($verbose > 1);
	if (($message =~ /\bp[oò]\b/)  and 
		!(($message =~ /\b(po'|po-)/) or ($message =~ /(\bPO|\.po\b|<filename>po\b)/))
	) {
		error("accento su \"po'\" sbagliato");
	}
}

sub check_si($)
{
	my $message = shift;
	print STDERR ("$source:$line checking \"sì\": $message\n") if ($verbose > 1);
	if ($message =~ /\bsi[,;:.!\?]/i) {
		error("manca accento su \"sì\"");
	}
	if ($message =~ /\b(far|fai|fa|fa')\s+i\b/i) {
		error("manca accento su \"sì\"");
	}
}

sub check_triple($)
{
	my $message = shift;
	print STDERR ("$source:$line checking triple: $message\n") if ($verbose > 1);
	# Sequenze di tre caratteri uguali. Ignora la linea se ci sono numeri esadecimali 0xffff ecc.
	if (($message =~ /([bcdfglmnprstvz])\1\1/i) and 
		!(
			($message =~ /(pppd?|kppp\w*)\b/i) or 
			($message =~ /0x/) or 
			($message =~/glossseealso/) or
			($message =~/\b([BCDFGLMNPRSTVZbcdfglmnprstvz])\1\1\1?\1?\1?\1?\1?\1?\1?\1?\b/)
		)
	) {
		error("sequenza di tre o più lettere uguali");
	}
}

sub check_double_vowels($)
{
	my $message = shift;
	print STDERR ("$source:$line checking double wovels: $message\n") if ($verbose > 1);
	# Sequenze di tre caratteri uguali. Ignora la linea se ci sono numeri esadecimali 0xffff ecc.
	if (($message =~ /([aeiou])\1/i) 
	) {
		error("sequenza di due o più vocali uguali");
	}
}

sub check_commas($)
{
	my $message = shift;
	print STDERR ("$source:$line checking: $message\n") if ($verbose > 1);
	# Sequenze di tre caratteri uguali. Ignora la linea se ci sono numeri esadecimali 0xffff ecc.
	if ($message =~ /,,/) {
		error("virgole ripetute");
	}
}

sub check_spaces($)
{
	my $message = shift;
	print STDERR ("$source:$line checking spaces in: $message\n") if ($verbose > 1);
	if (($message =~ / [\.,;:!\?]/) and
		!(
			($message =~ / !=/) or 
			($message =~ / \.[a-z]{1,3}/i)
		)
	) {
		error("spazio davanti a simboli di punteggiatura");
	}
	if (($message =~ /([\.!?,;])([a-zàèéìòù]+)/i) 
	) {
		if (
			!(
				($message =~ /^Keywords=/) or
				($message =~ /^Query=/)
			)
		) {
			if (	!(
					($1 eq '.' and $extension{$2} eq 't') or
					($message =~ "\.\.\.$2")
				)
			) {
				error("spazio mancante dopo simbolo di punteggiatura e prima di $2");
			}
		}
	}
	if (($message =~ /\(\s/) 
	) {
		error("spazio dopo una parentesi aperta");
	}
	if (($message =~ /\s\)/) 
	) {
		error("spazio prima di una parentesi chiusa");
	}
	# For KDE docbooks: extra spaces between selected tags
	if (($message =~ /<(application|email|keycap|menuitem|guibutton|guiicon|guilabel|guimenu|quote)>[^<]+\s<\/\1>/i)) {
		error("spazio prima del tag di chiusura <$1>");
	}
	if (($message =~ /<(keycombo)\s?.*>[^<]+\s<\/\1>/i)) {
		error("spazio prima del tag di chiusura <$1>");
	}
	if (($message =~ /<(application|email|keycap|menuitem|guibutton|guiicon|guilabel|guimenu|quote)\s?.*>\s[^<]+<\/\1>/i)) {
		error("spazio dopo il tag di apertura <$1>");
	}
	if (($message =~ /<(keycombo)\s?.*>\s[^<]+<\/\1>/i)) {
		error("spazio dopo il tag di apertura <$1>");
	}
}

sub check_accents($)
{
	my $message = shift;
	print STDERR ("$source:$line checking accents in: $message\n") if ($verbose > 1);
	if (
		($message =~ /(\b(lunedi|martedi|mercoledi|giovedi|venerdi)\b)/i) or 
		($message =~ /(\b(affinche|benche|bensi|gia|giu|puo|piu|cosi|percio|pero|perche|poiche)\b)/i) or
		($message =~ /(\b(cio|cioe)[,:\s])/i) or
		($message =~ /((venti|trenta|quaranta|cinquanta|sessanta|settanta|ottanta|novanta)tre\b)/i)
	) {
		my $match = $&;
		if (!($message =~ /($match)[àièéìíòùú]/)) {
			error("accento mancante su $match");
		}
	}
	if (($message =~ /\b(la)[\.,!\?;:]/i)) {
		error("Forse volevi dire \"là\"");
	}
	if (($message =~ /\b(li)[\.,!\?;:]/i)) {
		error("Forse volevi dire \"lì\"");
	}
	# KDE convention
	if (($message =~ /\b(menù|menú)[^w]/i)) {
		error("accento in eccesso");
	}
}

sub check_apostrophe($)
{
	my $message = shift;
	print STDERR ("$source:$line checking apostrophes in: $message\n") if ($verbose > 1);
	if (($message =~ /\b(alcun|ciascun|un|all|l)'([bcdfgklmnpqrstvz][a-z]+)\b/i)) {
		print STDERR ("$source:$line $1 matches apostrophe rule\n") if ($verbose > 0);
		if (!($gender{$2} eq 'f')) {
			error("apostrofo davanti a parola che inizia per consonante ($2)");
		}
	}
	if (($message =~ /\b(alcun|ciascun|un)'([aeiou][a-z]*o)\b/i)) {
		print STDERR ("$source:$line $1 matches apostrophe rule\n") if ($verbose > 0);
		if (!($gender{$2} eq 'f')) {
			error("apostrofo sbagliato davanti a $2");
		}
	}
	if (($message =~ /\b(alcun|ciascun|un)\s+([a-z]*a)\b/i)) {
		print STDERR ("$source:$line $1 matches apostrophe rule\n") if ($verbose > 0);
		print STDERR ("$source:$line gender of $1 is '$gender{$1}'\n") if ($verbose > 0);
		if (!($gender{$2} eq 'm')) {
			error("apostrofo mancante fra $1 e $2");
		}
	}
	if (($message =~ /\b(alcuna|ciascuna|la|una)\s+([a-z]+o)\b/i)) {
		my $article = $1;
		print STDERR ("$source:$line $1 matches apostrophe rule\n") if ($verbose > 0);
		# exclude feminine words, verbal forms and "la loro"
		if (
			($gender{$2} ne 'f') && 
			!($2 =~ /anno$/i) &&
			!($2 =~ /ano$/i) &&
			!($2 =~ /^loro$/i)
		) {
			error("parola maschile ($2) preceduta da $1");
		}
	}
}

sub check_qual($)
{
	my $message = shift;
	print STDERR ("$source:$line checking for 'qual': $message\n") if ($verbose > 1);
	if ($message =~ /\bqual'/i) {
		error("qual non va seguito dall'apostrofo");
	}
}

sub check_repeated($)
{
	my $message = shift;
	print STDERR ("$source:$line checking for repeated words: $message\n") if ($verbose > 1);
	if ($message =~ /(\b([a-z]{2,}) \1\b)/i) {
		my $match = $&;
		if (!$message =~ /($match)[àèìòùáéíóú]/) {
			error("parole ripetute");
		}
	}
}

sub check_e($)
{
	my $message = shift;
	print STDERR ("$source:$line checking for mistyped \"è\": $message\n") if ($verbose > 1);
	if (($message =~ /\sé\s/i) or ($message =~ /\be['`]\s/i)) {
		error("\"è\" scritto male");
	}
}

sub check_capitals($)
{
	my $message = shift;
	print STDERR ("$source:$line checking capitals in: $message\n") if ($verbose > 1);
	if (
		($message =~ /\b(Lunedì|Martedì|Mercoledì|Giovedì|Venerdì|Sabato|Domenica)\b/) or
		($message =~ /\b(Lun|Mart|Mer|Gio|Ven|Sab|Dom)\b/) or
		($message =~ /\b(Gennaio|Febraio|Marzo|Aprile|Maggio|Giugno|Luglio|Agosto|Settembre|Ottobre|Novembre|Dicembre)\b/) or
		($message =~ /\b(Gen|Feb|Mar|Apr|Mag|Giu|Lug|Ago|Set|Ott|Nov|Dic)\b/)
	) {
		error("mese o giorno della settimana in maiuscolo");
	}
}

sub check_english_plural($)
{
	my $message = shift;
	print STDERR ("$source:$line checking english plurals in: $message\n") if ($verbose > 1);
	if (
		($message =~ /[^\/]\b((m|k|g|)bytes|(m|k|g|)bits|bugs|downloads|uploads|plugins|directories|drivers|files|forms|skins|desktops|tags|sponsors|widgets|toolkits|newsgroups)\b[^\/]/i)
	) {
		error("plurale con la \"s\": $1");
	}
}

sub check_double_uppercase($)
{
	# DUe maiuscole all'inizio di una parola (di solito sono un
	# 	errore, ma ci sono eccezioni)
	my $message = shift;
	print STDERR ("$source:$line checking for double capitals: $message\n") if ($verbose > 1);
	# Special case for "K", since it's used in many KDE programs.
	if (($message =~ /\b([A-JL-WYZ]{2}[a-z]+)/)) {
		if (!($camelword{$1} eq 't')) {
			error("due lettere maiuscole all'inizio della parola $1");
		}
	}
}

sub check_missing_uppercase($)
{
	my $message = shift;
	print STDERR ("$source:$line checking for missing capitals: $message\n") if ($verbose > 1);
	# Special case for "K", since it's used in many KDE programs.
	if (($message =~ /([a-zàèìòùé]+)\.\s+[a-z]/)) {
		if (!($abbreviation{$1} eq 't')) {
			error("minuscola dopo un punto");
		}
	}
	if (($message =~ /([a-z]+)\.\s+è/)) {
		if (!($abbreviation{$1} eq 't')) {
			error("minuscola dopo un punto");
		}
	}
}

sub check_title_case($)
{
	my $message = shift;
	print STDERR ("$source:$line checking for title case: $message\n") if ($verbose > 1);
#	if (($message =~ /^([A-Z][a-z]+\s)+[A-Z][a-z]+$/)) {
#		error("sembra un titolo con maiuscole all'inglese: in italiano la convenzione non si usa.");
#	}
	if (($message =~ /<(menuitem|guibutton|guiicon|guilabel|guimenu)>([A-Z][a-z]+\s)+[A-Z][a-z]+<\/\1>/)) {
		error("sembra un titolo com maiuscole all'inglese: in italiano la convenzione non si usa.");
	}
}

sub check_bad_phrases($)
{
	my $message = shift;
	print STDERR ("$source:$line checking for click: $message\n") if ($verbose > 1);
	# Special case for "K", since it's used in many KDE programs.
	if (($message =~ /\bclick\b/i)) {
		error("usa \"clic\", non \"click\".");
	}
	if (($message =~ /\b(clicca|clicchi|cliccare|cliccate|cliccando)\b/i)) {
		error("usa \"fare clic\", non \"cliccare\".");
	}
	if (($message =~ /\b(indenta)/i)) {
		error("usa rientro, non indentazione.");
	}
	if (($message =~ /\b(botton)/i)) {
		error("usa tasto o pulsante, non bottone.");
	}
	if (($message =~ /\b(affianco)/i)) {
		error("usa a fianco non affianco.");
	}
}

sub check_qu($)
{
	my $message = shift;
	# Special case for "K", since it's used in many KDE programs.
	if (($message =~ /q[aeio]/i)) {
		error("'Q' non seguita da 'u'");
	}
}

sub check_runtogether_words($)
{
	my $message = shift;
	# Special case for "K", since it's used in many KDE programs.
	if (($message =~ /([a-z]+(per|sul|degli|dal|con|il))[^a-zàèìòùé]/i)) {
		if (!($notruntogether{$1} eq 't')) {
			error("$2 attaccato alla parola precedente ($1)?");
		}
	}
	if (($message =~ /[^a-zàèìòùé](degli|dalla)([a-zàèìòùé]+)/i)) {
		if (!($notruntogether{$1} eq 't')) {
			error("$1 attaccato alla parola successiva ($2)?");
		}
	}
}


sub check_gender($)
{
	my $message = shift;
	print STDERR ("$source:$line checking foreign world gender: $message\n") if ($verbose > 1);
	# Special case for "K", since it's used in many KDE programs.
	my $firstword = "alla|alle|dalla|dalle|della|delle|nella|nelle|colla|colle|sulla|sulle|ciascuna|la|le|una|altra";
	if (($message =~ /\b($firstword)\s+(stack|tag|joystick|url|uri)\b/i)) {
		my $match = $2;
		error("la convenzione usata per $match è di usare il maschile ($1)");
	}
}

sub check_ing($)
{
	my $message = shift;
	print STDERR ("$source:$line checking for -ing: $message\n") if ($verbose > 1);
	# Special case for "K", since it's used in many KDE programs.
	if (($message =~ /\b([a-z]+ing)\b/i)) {
		my $matvh = $1;
		error("è preferita la forma all'infinito a quella in -ing per $match.");
	}
}

sub check_conflict_marker($)
{
	my $message = shift;
	print STDERR ("$source:$line checking for conflict marker: $message\n") if ($verbose > 1);
	# Special case for "K", since it's used in many KDE programs.
	if (($message =~ />>>>>>/)) {
		my $matvh = $1;
		error("possibile rimasuglio di un conflitto CVS/SVN");
	}
}

sub check_common_mistyping($)
{
	my $message = shift;
	print STDERR ("$source:$line checking for fancy capitalization: $message\n") if ($verbose > 1);
	if ($message =~ /\bpostscript\b/i) {
		if (!($message =~ /\bPostScript\b/)) {
			error("normalmente, PostScript si scrive con la 'P' e la 'S'  maiuscola");
		}
	}
	if ($message =~ /\bamarok\b/i) {
		if (!($message =~ /\bAmarok\b/)) {
			error("attualmente, Amarok si scrive con l'iniziale (e solo quella) maiuscola");
		}
	}
	if ($message =~ /\bkonqueror\b/i) {
		if (!($message =~ /\bKonqueror\b/)) {
			error("normalmente, Konqueror si scrive con la maiuscola");
		}
	}
	# Errori trovati da aspell -- corretti su HEAD, devo assicurarmi di eliminarli sul branch
	if ($message =~ /\bcomprarir/i) {
		error("\"comparire\", non \"comprarire\"");
	}
	if ($message =~ /\bconneter/i) {
		error("\"connettere\", non \"connetere\"");
	}
	if ($message =~ /\bcondividire\b/i) {
		error("\"condividere\", non \"condividire\"");
	}
	if ($message =~ /\bconcella/i) {
		error("\"cancellare\", non \"concellare\"");
	}
	if ($message =~ /\bconfgura/i) {
		error("\"configurare\", non \"confgurare\"");
	}
	if ($message =~ /\bcompueter\b/i) {
		error("\"computer\", non \"compueter\"");
	}
	if ($message =~ /\bconemporane/i) {
		error("\"contemporaneo\", non \"conemoraneo\"");
	}
	if ($message =~ /\bcomportamente/i) {
		error("\"comportamento\", non \"comportamente\"");
	}
	if ($message =~ /\bcomuncazione/i) {
		error("\"comunicazione\", non \"comuncazione\"");
	}
	if ($message =~ /\bcondifica/i) {
		error("\"codifica\", non \"condifica\"");
	}
	if ($message =~ /\bconfendo\b/i) {
		error("\"confendo\"?");
	}
	if ($message =~ /\bdaccordo\b/i) {
		error("\"d'accordo\", non \"daccordo\"");
	}
	if ($message =~ /\bdaltronde\b/i) {
		error("\"d'altronde\", non \"daltronde\"");
	}
	if ($message =~ /efficen(za|te|ti|temente)\b/i) {
		error("\"efficienza\", non \"efficenza\"");
	}
	if ($message =~ /\bevacq\w+\b/i) {
		error("\"evacuare\", non \"evacquare\"");
	}
	if ($message =~ /\binnoqu[aeio]\b/i) {
		error("\"innocuo\", non \"innoquo\"");
	}
	if ($message =~ /\b(obbiettiv[aeio])\b/i) {
		error("troppe 'b' in \"$1\"");
	}
	if ($message =~ /\bpercui\b/i) {
		error("\"per cui\", non \"percui\"");
	}
	if ($message =~ /\bpropi[aeo]\b/i) {
		error("\"proprio\", non \"propio\"");
	}
	if ($message =~ /propietà/i) {
		error("\"proprietà\", non \"propietà\"");
	}
	if ($message =~ /\bsopratutto\b/i) {
		error("\"soprattutto\", non \"sopratutto\"");
	}
	if ($message =~ /sufficent[ei]\b/i) {
		error("\"sufficiente\", non \"sufficente\"");
	}
	if ($message =~ /sufficenza\b/i) {
		error("\"sufficienza\", non \"sufficenza\"");
	}
	if ($message =~ /(\w+zzion\w+)/i) {
		error("'z' in eccesso in \"$1\"");
	}
	if ($message =~ /\b(and|or)\b/i) {
		error("congiunzione inglese -possibile refuso");
	}
	if (
		($message =~ /(\w+mnete\w+)/i) || 
		($message =~ /(\w+metne\w+)/i)
	) {
		error("'-mente scritto male in \"$1\"?");
	}
}

sub check_aspell($)
{
	my $message = shift;
	if ($message =~ /^(X-Generator|Content-|POT-|Language-|Project-Id-|Report-Msgid-Bugs-To|X-KDE-DocBook-|Plural-Forms)/) {
		return;
	}
	# Strip common docbook tags before spell check
	my $xmlKeywords = "application|address|affiliation|contrib|em|email|" . 
			  "firstname|keycombo|keycap|" . 
			  "envar|keyword|group|filename|" .
			  "menuitem|guibutton|guiicon|guilabel|" . 
			  "guimenu|" .
			  "command|computeroutput|option|" .
			  "abbrev|acronym|" .
			  "citation|firstterm|quote|emph|emphasis|";
	$message =~ s/<($xmlKeywords)>//ig;
	$message =~ s/<\/($xmlKeywords)>//ig;
	$message =~ s/<($xmlKeywords) \/>//ig;

	my $xmlKeywords = "guimenuitem|guisubmenu|br|center"; 
	$message =~ s/<($xmlKeywords)>/ /ig;
	$message =~ s/<\/($xmlKeywords)>/ /ig;
	$message =~ s/<($xmlKeywords) \/>/ /ig;

	# remove email addresses
	$message =~ s/[a-z0-9_]*@[a-z0-9_\.]*/ /i;
	$message =~ s/(ftp|http|https):\/\/[a-z0-9_@\?\.\/]*/ /i;
	$message =~ s/%[0-9n]/ /ig;
	$message =~ s/[0-9]+[a-zA-Z]*/ /ig;
	#my @list = split(/[ \t\n\,\.\?!#-=+\\\/><\|\{\}\[\]\"]/, $message);
	my @list = split(/[ \t\n,\.;\?!|:\/\\\"()\{\}\[\]=\-+\*\&<>]/, $message);
	#error(@list);
	for $i (@list) {
		if (!$speller->check($i)) {
			if (!($unknownWords{$i} eq 't')) {
				error("Parola sconosciuta: $i");
				$unknownWords{$i} = 't';
				#open(WORDS, ">>dict");
				#print WORDS ("$i\n");
				#close WORDS;
			}
		}
	}
}

sub check_wesnoth($)
{
	my $message = shift;
	if ($message =~ /\blancier[aei]\b/i) {
		error("se l'unità è a piedi, usa \"fante\"");
	}
	if ($message =~ /\bnereide[ei] siren[ae]\b/i) {
		error("Nel nome dell'unità \"nereide\" non è necessario");
	}
	if ($message =~ /\bsiren[ae] nereide[ei]\b/i) {
		error("Nel nome dell'unità \"nereide\" non è necessario");
	}
	if ($message =~ /\btritone[ei] nereide[ei]\b/i) {
		error("Nel nome dell'unità \"nereide\" non è necessario");
	}
	if ($message =~ /\bfat[ae] elfic(a|he)\b/i) {
		error("Nel nome dell'unità \"elfica\" non è necessario");
	}
	if ($message =~ /\bninfa[ae] elfic(a|he)\b/i) {
		error("Nel nome dell'unità \"elfica\" non è necessario");
	}
	if ($message =~ /\bdriad[ei] elfic(a|he)\b/i) {
		error("Nel nome dell'unità \"elfica\" non è necessario");
	}if ($message =~ /\bdrag(o|hi) impositor(e|i)\b/i) {
		error("Il nome dell'unità è stato cambiato in \"Drago vigilante\"");
	}
	if ($message =~ /\bdrag(o|hi) sfregiator(e|i)\b/i) {
		error("Il nome dell'unità è stato cambiato in \"Drago sventratore\"");
	}
	if ($message =~ /\bpiaga\b/i) {
		error("Usa \"Contagio\"");
	}
}

sub check_ai($)
{
	my $message = shift;
	if ($message =~ /\banno [a-zA-Z]\+to\b/i) {
		error("Controlla: anno o hanno?");
	}
	if ($message =~ /\bo [a-zA-Z]\+to\b/i) {
		error("Controlla: o o ho?");
	}
	if ($message =~ /\bai [a-zA-Z]\+to\b/i) {
		error("Controlla: ai o hai?");
	}
}

sub check_salva_come($)
{
	my $message = shift;
	if ($message =~ /\bsalva con nome/i) {
		error("Usa Salva come");
	}
}

sub printUsage()
{
	print STDERR ("Usage: $0 {-wp} file\n");
	print STDERR ("\n");
	print STDERR ("-w esegui i controlli sui messaggi completi invece che riga per riga\n");
	print STDERR ("-p tratta il file come un file di puro testo (non un file .po)\n");
	
}
