From c65c25c59074eaa09621f4fd782362b2c5227e32 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Tue, 24 Apr 2007 23:55:24 +0000 Subject: fmtcount 1.09 (24apr07) git-svn-id: svn://tug.org/texlive/trunk@4182 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/doc/latex/fmtcount/CHANGES | 11 + Master/texmf-dist/doc/latex/fmtcount/README | 4 +- Master/texmf-dist/doc/latex/fmtcount/fc-lang.tex | 14 +- Master/texmf-dist/doc/latex/fmtcount/fc-samp.tex | 3 +- Master/texmf-dist/doc/latex/fmtcount/fmtcount.pdf | Bin 121492 -> 133652 bytes Master/texmf-dist/doc/latex/fmtcount/fmtcount.perl | 470 ++++++++++++++++++++- Master/texmf-dist/doc/latex/fmtcount/manual.html | 148 +++++-- 7 files changed, 608 insertions(+), 42 deletions(-) (limited to 'Master/texmf-dist/doc') diff --git a/Master/texmf-dist/doc/latex/fmtcount/CHANGES b/Master/texmf-dist/doc/latex/fmtcount/CHANGES index 412416bd5d7..13afa7d9565 100644 --- a/Master/texmf-dist/doc/latex/fmtcount/CHANGES +++ b/Master/texmf-dist/doc/latex/fmtcount/CHANGES @@ -1,5 +1,16 @@ fmtcount package versions: +Version 1.09: Added upper case variants \ORDINALstring etc +(\MakeUppercase{\ordinalstring{}} doesn't work because +of the way \MakeUppercase expands its argument). + +Added commands to store textual representations \storeordinalstring etc + +Version 1.08: fixed Portugues spelling mistakes (tr\`es -> tr\^es +centa -> cento) + +Version 1.07: fixed bug that causes fc-english.def to be loaded twice + Version 1.06: fixed language-related bug Version 1.05: fixed bug in \padzeroes diff --git a/Master/texmf-dist/doc/latex/fmtcount/README b/Master/texmf-dist/doc/latex/fmtcount/README index bad070ef6f2..6d2c2d426f0 100644 --- a/Master/texmf-dist/doc/latex/fmtcount/README +++ b/Master/texmf-dist/doc/latex/fmtcount/README @@ -1,6 +1,6 @@ -LaTeX Package : fmtcount v 1.06 +LaTeX Package : fmtcount v 1.09 -Last Modified : 6 January 2007 +Last Modified : 21 April 2007 Author : Nicola Talbot diff --git a/Master/texmf-dist/doc/latex/fmtcount/fc-lang.tex b/Master/texmf-dist/doc/latex/fmtcount/fc-lang.tex index 3600e0b5abd..0c81dc887fd 100644 --- a/Master/texmf-dist/doc/latex/fmtcount/fc-lang.tex +++ b/Master/texmf-dist/doc/latex/fmtcount/fc-lang.tex @@ -138,8 +138,10 @@ Current language: French (Belgium). \typeout{Which format?^^J} \typeout{[1] ordinalstring} \typeout{[2] Ordinalstring} -\typeout{[3] numberstring} -\typeout{[4] Numberstring} +\typeout{[3] ORDINALstring} +\typeout{[4] numberstring} +\typeout{[5] Numberstring} +\typeout{[6] NUMBERstring} \typein[\response]{Default: 1} @@ -147,16 +149,20 @@ Current language: French (Belgium). \ifthenelse{\equal{\response}{1}}{\myctr=1}{ \ifthenelse{\equal{\response}{2}}{\myctr=2}{ \ifthenelse{\equal{\response}{3}}{\myctr=3}{ -\ifthenelse{\equal{\response}{4}}{\myctr=4}{\myctr=-1 -\typeout{Invalid response '\response', please select a number from 1 to 4}}}}} +\ifthenelse{\equal{\response}{4}}{\myctr=4}{ +\ifthenelse{\equal{\response}{5}}{\myctr=5}{ +\ifthenelse{\equal{\response}{6}}{\myctr=6}{\myctr=-1 +\typeout{Invalid response '\response', please select a number from 1 to 4}}}}}}} \ifnum\myctr=-1 \repeat \ifcase\myctr \or\def\stringtype{ordinalstring} \or\def\stringtype{Ordinalstring} +\or\def\stringtype{ORDINALstring} \or\def\stringtype{numberstring} \or\def\stringtype{Numberstring} +\or\def\stringtype{NUMBERstring} \fi \ifnum\langid>3 diff --git a/Master/texmf-dist/doc/latex/fmtcount/fc-samp.tex b/Master/texmf-dist/doc/latex/fmtcount/fc-samp.tex index 4c5a6e47f4e..1a18321c004 100644 --- a/Master/texmf-dist/doc/latex/fmtcount/fc-samp.tex +++ b/Master/texmf-dist/doc/latex/fmtcount/fc-samp.tex @@ -120,7 +120,8 @@ numberstring Referencing a label: \ref{ex}. Passing numbers explicitly: \ordinalnum{10}, -\Numberstringnum{10}, \Ordinalstringnum{10}. +\Numberstringnum{10}, \NUMBERstringnum{10}, \Ordinalstringnum{10}, +\ORDINALstringnum{10}. \end{document} \endinput diff --git a/Master/texmf-dist/doc/latex/fmtcount/fmtcount.pdf b/Master/texmf-dist/doc/latex/fmtcount/fmtcount.pdf index 8f4ba512f43..64163d43156 100644 Binary files a/Master/texmf-dist/doc/latex/fmtcount/fmtcount.pdf and b/Master/texmf-dist/doc/latex/fmtcount/fmtcount.pdf differ diff --git a/Master/texmf-dist/doc/latex/fmtcount/fmtcount.perl b/Master/texmf-dist/doc/latex/fmtcount/fmtcount.perl index 875f41febc1..2cf6bb3a091 100644 --- a/Master/texmf-dist/doc/latex/fmtcount/fmtcount.perl +++ b/Master/texmf-dist/doc/latex/fmtcount/fmtcount.perl @@ -1,7 +1,7 @@ # File : fmtcount.perl # Author : Nicola Talbot -# Date : 3 Mar 2005 -# Version : 1.02 +# Date : 21 April 2007 +# Version : 1.04 # Description : LaTeX2HTML implementation of fmtcount package package main; @@ -171,6 +171,58 @@ sub do_cmd_ordinal{ } } +sub do_cmd_storeordinal{ + local($_) = @_; + local($key); + + $key = &missing_braces + unless ((s/$next_pair_pr_rx//o)&&($key=$2)); + + local($ctr, $val, $id, $_) = &read_counter_value($_); + local($gender)='m'; + + $_ =~ s/${OP}$id${CP}$ctr${OP}$id${CP}//; + + if ($_ =~s/\s*\[(.)\]//) + { + $gender = $1; + } + + if ($ctr eq 'DAY' or $ctr eq 'MONTH' or $ctr eq 'YEAR') + { + # this is a cludge to make it work with newdateformat + $fmtcntvar{$key} = join('', '{ORDINAL{', $ctr, '}}'); + } + else + { + $fmtcntvar{$key} = &getordinal($val, $gender); + } + + $_; +} + +sub do_cmd_storeordinalnum{ + local($_) = @_; + local($key, $val); + + $key = &missing_braces + unless ((s/$next_pair_pr_rx//o)&&($key=$2)); + + $val = &missing_braces + unless ((s/$next_pair_pr_rx//o)&&($val=$2)); + + local($gender)='m'; + + if ($_ =~s/\s*\[(.)\]//) + { + $gender = $1; + } + + $fmtcntvar{$key} = &getordinal($val, $gender); + + $_; +} + @unitthstring = ('zeroth', 'first', 'second', @@ -496,7 +548,7 @@ $thousandthnamespanish = "mil\\'esimo"; @unitstringportuges = ('zero', 'um', 'dois', - 'tr\`es', + 'tr\^es', 'quatro', 'cinco', 'seis', @@ -762,7 +814,7 @@ sub get_numberstringportuges{ { $hundreds = $hundredstringportuges[$num/100]; - if ($gender eq 'f') + if ($gender eq 'f' and $num >= 200) { $hundreds =~s/o(s?)$/a\1/; } @@ -860,6 +912,58 @@ sub do_cmd_numberstring{ } } +sub do_cmd_storenumberstring{ + local($_) = @_; + local($key); + + $key = &missing_braces + unless ((s/$next_pair_pr_rx//o)&&($key=$2)); + + local($ctr, $val, $id, $_) = &read_counter_value($_); + local($gender)='m'; + + $_ =~ s/${OP}$id${CP}$ctr${OP}$id${CP}//; + + if ($_ =~s/\s*\[(.)\]//) + { + $gender = $1; + } + + if ($ctr eq 'DAY' or $ctr eq 'MONTH' or $ctr eq 'YEAR') + { + # this is a cludge to make it work with newdateformat + $fmtcntvar{$key} = join('', '{NUMBERSTRING{', $ctr, '}}'); + } + else + { + $fmtcntvar{$key} = join('', &get_numberstring($val, $gender)); + } + + $_; +} + +sub do_cmd_storenumberstringnum{ + local($_) = @_; + local($key, $val); + + $key = &missing_braces + unless ((s/$next_pair_pr_rx//o)&&($key=$2)); + + $val = &missing_braces + unless ((s/$next_pair_pr_rx//o)&&($val=$2)); + + local($gender)='m'; + + if ($_ =~s/\s*\[(.)\]//) + { + $gender = $1; + } + + $fmtcntvar{$key} = join('', &get_numberstring($val, $gender)); + + $_; +} + sub get_Numberstring{ local($val,$gender) = @_; local($string) = &get_numberstring($val,$gender); @@ -925,6 +1029,150 @@ sub do_cmd_Numberstring{ } } +sub do_cmd_storeNumberstring{ + local($_) = @_; + local($key); + + $key = &missing_braces + unless ((s/$next_pair_pr_rx//o)&&($key=$2)); + + local($ctr, $val, $id, $_) = &read_counter_value($_); + local($gender)='m'; + + $_ =~ s/${OP}$id${CP}$ctr${OP}$id${CP}//; + + if ($_ =~s/\s*\[(.)\]//) + { + $gender = $1; + } + + if ($ctr eq 'DAY' or $ctr eq 'MONTH' or $ctr eq 'YEAR') + { + # this is a cludge to make it work with newdateformat + $fmtcntvar{$key} = join('', '{NNUMBERSTRING{', $ctr, '}}'); + } + else + { + $fmtcntvar{$key} = join('', &get_Numberstring($val, $gender)); + } + + $_; +} + +sub do_cmd_storeNumberstringnum{ + local($_) = @_; + local($key, $val); + + $key = &missing_braces + unless ((s/$next_pair_pr_rx//o)&&($key=$2)); + + $val = &missing_braces + unless ((s/$next_pair_pr_rx//o)&&($val=$2)); + + local($gender)='m'; + + if ($_ =~s/\s*\[(.)\]//) + { + $gender = $1; + } + + $fmtcntvar{$key} = join('', &get_Numberstring($val, $gender)); + + $_; +} + +sub do_cmd_NUMBERstringnum{ + local($_) = @_; + local($num,$gender); + $num = &missing_braces + unless (($_[0]=~s/$next_pair_pr_rx//o)&&($num=$2)); + + if ($_[0] =~ s/\[(m|f)\]//) + { + $gender = $1; + } + else + { + $gender = 'm'; + } + + join('', uc(&get_numberstring($num,$gender)), $_[0]); +} + +sub do_cmd_NUMBERstring{ + local($ctr, $val, $id, $_) = &read_counter_value($_[0]); + local($gender)='m'; + + $_[0] =~ s/${OP}$id${CP}$ctr${OP}$id${CP}//; + + if ($_[0]=~s/\[(.)\]//) + { + $gender = $1; + } + + if ($ctr eq 'DAY' or $ctr eq 'MONTH' or $ctr eq 'YEAR') + { + # this is a cludge to make it work with newdateformat + join('', '{CAPNUMBERSTRING{', $ctr, '}}', $_); + } + else + { + join('', uc(&get_numberstring($val, $gender)), $_); + } +} + +sub do_cmd_storeNUMBERstring{ + local($_) = @_; + local($key); + + $key = &missing_braces + unless ((s/$next_pair_pr_rx//o)&&($key=$2)); + + local($ctr, $val, $id, $_) = &read_counter_value($_); + local($gender)='m'; + + $_ =~ s/${OP}$id${CP}$ctr${OP}$id${CP}//; + + if ($_ =~s/\s*\[(.)\]//) + { + $gender = $1; + } + + if ($ctr eq 'DAY' or $ctr eq 'MONTH' or $ctr eq 'YEAR') + { + # this is a cludge to make it work with newdateformat + $fmtcntvar{$key} = join('', '{CAPNUMBERSTRING{', $ctr, '}}'); + } + else + { + $fmtcntvar{$key} = uc(&get_numberstring($val, $gender)); + } + + $_; +} + +sub do_cmd_storeNUMBERstringnum{ + local($_) = @_; + local($key, $val); + + $key = &missing_braces + unless ((s/$next_pair_pr_rx//o)&&($key=$2)); + + $val = &missing_braces + unless ((s/$next_pair_pr_rx//o)&&($val=$2)); + + local($gender)='m'; + + if ($_ =~s/\s*\[(.)\]//) + { + $gender = $1; + } + + $fmtcntvar{$key} = uc(&get_numberstring($val, $gender)); + + $_; +} + sub get_ordinalstringenglish{ local($num) = @_; local($name)=""; @@ -1361,18 +1609,82 @@ sub do_cmd_ordinalstring{ if ($ctr eq 'DAY' or $ctr eq 'MONTH' or $ctr eq 'YEAR') { # this is a cludge to make it work with newdateformat - join('', '{ORDINALSTRING{', $ctr, '}}', $_[0]); + join('', '{ORDINALSTRING{', $ctr, '}}', $_); } else { - join('', &get_ordinalstring($val, $gender), $_[0]); + join('', &get_ordinalstring($val, $gender), $_); } } + %fmtcntvar = (); + +sub do_cmd_FMCuse{ + local($_) = @_; + local($key); + + $key = &missing_braces + unless ((s/$next_pair_pr_rx//o)&&($key=$2)); + + $fmtcntvar{$key}.$_; +} + +sub do_cmd_storeordinalstring{ + local($_) = @_; + local($key); + + $key = &missing_braces + unless ((s/$next_pair_pr_rx//o)&&($key=$2)); + + local($ctr, $val, $id, $_) = &read_counter_value($_); + local($gender)='m'; + + $_ =~ s/${OP}$id${CP}$ctr${OP}$id${CP}//; + + if ($_ =~s/\s*\[(.)\]//) + { + $gender = $1; + } + + if ($ctr eq 'DAY' or $ctr eq 'MONTH' or $ctr eq 'YEAR') + { + # this is a cludge to make it work with newdateformat + $fmtcntvar{$key} = join('', '{ORDINALSTRING{', $ctr, '}}'); + } + else + { + $fmtcntvar{$key} = join('', &get_ordinalstring($val, $gender)); + } + + $_; +} + +sub do_cmd_storeordinalstringnum{ + local($_) = @_; + local($key, $val); + + $key = &missing_braces + unless ((s/$next_pair_pr_rx//o)&&($key=$2)); + + $val = &missing_braces + unless ((s/$next_pair_pr_rx//o)&&($val=$2)); + + local($gender)='m'; + + if ($_ =~s/\s*\[(.)\]//) + { + $gender = $1; + } + + $fmtcntvar{$key} = join('', &get_ordinalstring($val, $gender)); + + $_; +} + sub get_Ordinalstring{ local($val,$gender) = @_; local($string) = &get_ordinalstring($val,$gender); - $string =~ s/([a-z])([^\s\-]+)/\u\1\2/g; + $string =~ s/\b([a-z])([^\s\-]+)/\u\1\2/g; if ($default_language eq 'french') { @@ -1426,6 +1738,150 @@ sub do_cmd_Ordinalstring{ } } +sub do_cmd_storeOrdinalstring{ + local($_) = @_; + local($key); + + $key = &missing_braces + unless ((s/$next_pair_pr_rx//o)&&($key=$2)); + + local($ctr, $val, $id, $_) = &read_counter_value($_); + local($gender)='m'; + + $_ =~ s/${OP}$id${CP}$ctr${OP}$id${CP}//; + + if ($_ =~s/\s*\[(.)\]//) + { + $gender = $1; + } + + if ($ctr eq 'DAY' or $ctr eq 'MONTH' or $ctr eq 'YEAR') + { + # this is a cludge to make it work with newdateformat + $fmtcntvar{$key} = join('', '{OORDINALSTRING{', $ctr, '}}'); + } + else + { + $fmtcntvar{$key} = join('', &get_Ordinalstring($val, $gender)); + } + + $_; +} + +sub do_cmd_storeOrdinalstringnum{ + local($_) = @_; + local($key, $val); + + $key = &missing_braces + unless ((s/$next_pair_pr_rx//o)&&($key=$2)); + + $val = &missing_braces + unless ((s/$next_pair_pr_rx//o)&&($val=$2)); + + local($gender)='m'; + + if ($_ =~s/\s*\[(.)\]//) + { + $gender = $1; + } + + $fmtcntvar{$key} = join('', &get_Ordinalstring($val, $gender)); + + $_; +} + +sub do_cmd_ORDINALstringnum{ + local($_) = @_; + local($num,$gender); + $num = &missing_braces + unless (($_[0]=~s/$next_pair_pr_rx//o)&&($num=$2)); + + if ($_[0] =~ s/\[(m|f)\]//) + { + $gender = $1; + } + else + { + $gender = 'm'; + } + + join('', uc(&get_ordinalstring($num,$gender)), $_[0]); +} + +sub do_cmd_ORDINALstring{ + local($ctr, $val, $id, $_) = &read_counter_value($_[0]); + local($gender)='m'; + + $_[0] =~ s/${OP}$id${CP}$ctr${OP}$id${CP}//; + + if ($_[0]=~s/\[(.)\]//) + { + $gender = $1; + } + + if ($ctr eq 'DAY' or $ctr eq 'MONTH' or $ctr eq 'YEAR') + { + # this is a cludge to make it work with newdateformat + join('', '{CAPORDINALSTRING{', $ctr, '}}', $_); + } + else + { + join('', uc(&get_ordinalstring($val, $gender)), $_); + } +} + +sub do_cmd_storeORDINALstring{ + local($_) = @_; + local($key); + + $key = &missing_braces + unless ((s/$next_pair_pr_rx//o)&&($key=$2)); + + local($ctr, $val, $id, $_) = &read_counter_value($_); + local($gender)='m'; + + $_ =~ s/${OP}$id${CP}$ctr${OP}$id${CP}//; + + if ($_ =~s/\s*\[(.)\]//) + { + $gender = $1; + } + + if ($ctr eq 'DAY' or $ctr eq 'MONTH' or $ctr eq 'YEAR') + { + # this is a cludge to make it work with newdateformat + $fmtcntvar{$key} = join('', '{CAPORDINALSTRING{', $ctr, '}}'); + } + else + { + $fmtcntvar{$key} = uc(&get_ordinalstring($val, $gender)); + } + + $_; +} + +sub do_cmd_storeORDINALstringnum{ + local($_) = @_; + local($key, $val); + + $key = &missing_braces + unless ((s/$next_pair_pr_rx//o)&&($key=$2)); + + $val = &missing_braces + unless ((s/$next_pair_pr_rx//o)&&($val=$2)); + + local($gender)='m'; + + if ($_ =~s/\s*\[(.)\]//) + { + $gender = $1; + } + + $fmtcntvar{$key} = uc(&get_ordinalstring($val, $gender)); + + $_; +} + sub do_cmd_fmtcountsetoptions{ local($_) = @_; local($options) = &missing_braces unless ($_[0]=~(s/$next_pair_pr_rx//o)&&($options=$2)); diff --git a/Master/texmf-dist/doc/latex/fmtcount/manual.html b/Master/texmf-dist/doc/latex/fmtcount/manual.html index d8ae7bd7712..c1cbfa97cc8 100644 --- a/Master/texmf-dist/doc/latex/fmtcount/manual.html +++ b/Master/texmf-dist/doc/latex/fmtcount/manual.html @@ -7,8 +7,8 @@ original version by: Nikos Drakos, CBLU, University of Leeds Jens Lippmann, Marek Rouchal, Martin Wilck and others --> -fmtcount.sty v1.06: Displaying the Values of LaTeX Counters - +fmtcount.sty v1.09: Displaying the Values of LaTeX Counters + @@ -32,10 +32,10 @@ original version by: Nikos Drakos, CBLU, University of Leeds

-

fmtcount.sty v1.06: Displaying the Values of +

fmtcount.sty v1.09: Displaying the Values of LaTeX Counters

Nicola L.C. Talbot

-

6 January 2007

+

21st April 2007


@@ -44,25 +44,25 @@ Contents @@ -139,11 +139,20 @@ The macro \numberstring{counter} will print the \numberstring, but with initial letters in uppercase. For example, \Numberstring{section} will produce: Three. +The macro \NUMBERstring{counter} does the same +as \numberstring, but converted to upper case. Note that +\MakeUppercase{\NUMBERstring{counter}} doesn't +work, due to the way that \MakeUppercase expands its +argument1. +

-The macros \numberstringnum and -\Numberstringnum work like -\numberstring and -\Numberstring, respectively, but take an actual number +The macros \numberstringnum, +\Numberstringnum and +\NUMBERstringnum work like +\numberstring, +\Numberstring and +\NUMBERstring, respectively, but take an actual number rather than a counter as the argument. For example: \Numberstringnum{105} will produce: One Hundred and Five. @@ -154,15 +163,91 @@ The macro \ordinalstring{counter} will print th The macro \Ordinalstring{counter} does the same as \ordinalstring, but with initial letters in uppercase. For example, \Ordinalstring{section} will produce: Third. + + The macro \ORDINALstring{counter} does the same as +\ordinalstring, but with all words in upper case (see previous +note about \MakeUppercase).

-The macros \ordinalstringnum and -\Ordinalstringnum work like -\Ordinalstring and -\Ordinalstring, respectively, but take an actual number +The macros \ordinalstringnum, +\Ordinalstringnum and \ORDINALstringnum work like +\ordinalstring, +\Ordinalstring and \ORDINALstring, respectively, but take an actual number rather than a counter as the argument. For example, \ordinalstringnum{3} will produce: third. +

+As from version 1.09, textual representations can be stored for +later use. This overcomes the problems encountered when you +attempt to use one of the above commands in \edef. + +

+Each of the following commands takes a label as the first argument, +the other arguments are as the analogous commands above. These +commands do not display anything, but store the textual +representation. This can later be retrieved using +\FMCuse{label}. +Note: with \storeordinal and \storeordinalnum, the +only bit that doesn't get expanded is \fmtord. So, for +example, \storeordinalnum{mylabel}{3} will be stored as +3\relax \fmtord{rd}. + +

+ +\storeordinal{label}{counter}[gender] + +

+ +\storeordinalstring{label}{counter}[gender] + +

+ +\storeOrdinalstring{label}{counter}[gender] + +

+ +\storeORDINALstring{label}{counter}[gender] + +

+ +\storenumberstring{label}{counter}[gender] + +

+ +\storeNumberstring{label}{counter}[gender] + +

+ +\storeNUMBERstring{label}{counter}[gender] + +

+ +\storeordinalnum{label}{number}[gender] + +

+ +\storeordinalstring{label}{number}[gender] + +

+ +\storeOrdinalstringnum{label}{number}[gender] + +

+ +\storeORDINALstringnum{label}{number}[gender] + +

+ +\storenumberstring{label}{number}[gender] + +

+ +\storeNumberstring{label}{number}[gender] + +

+ +\storeNUMBERstring{label}{number}[gender] +

The macro \binary{counter} will print the value of counter as a binary number. @@ -306,8 +391,8 @@ Version 1.02 of the fmtcount package now has limited multilingual support. The following languages are implemented: English, Spanish, Portuguese, French, French (Swiss) and French (Belgian). The package checks to see if the -command \datelanguage is defined1, and will +command \datelanguage is defined2, and will load the code for those languages. The commands \ordinal, \ordinalstring and \numberstring (and their variants) will then be formatted in the currently @@ -418,7 +503,7 @@ Troubleshooting

-There is a FAQ available at: http://theoval.cmp.uea.ac.uk/~nlct/latex/packages/faq/.

@@ -435,12 +520,19 @@ University of East Anglia Norwich. NR4 7TJ.
United Kingdom. -
http://theoval.cmp.uea.ac.uk/~nlct/


Footnotes

-
... defined... +argument1
+
See all the various postings to +comp.text.tex about \MakeUppercase + +
+
... defined2
this will be true if you have loaded babel @@ -451,7 +543,7 @@ will be true if you have loaded babel Nicola L. C. Talbot. School of Computing Sciences. University of East Anglia. -Last Modified: 2007-01-06 +Last Modified: 2007-04-21 -- cgit v1.2.3