#!/usr/bin/perl
#
# Copyright 2002 Brown University
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#------------------------------------------------------------------------
#   colorcomb
#
#	Generate a table of text-on-background-color combinations
#	using only web-safe colors.  This is a perl CGI script.
#
#	Author: John Bazik
#		jsb@cs.brown.edu
#		http://www.cs.brown.edu/~jsb/
#
#	History:
#		30jun99 jsb	- original
#		26sep02 jsb	- fixed some typos that broke mozilla
#
use CGI;

#
#   Hue-sorted list of web-safe colors.
#
my @webcols=(
'330000', '663333', '660000', '996666', '993333', '990000', 'cc9999', 'cc6666',
'cc3333', 'cc0000', 'ffcccc', 'ff9999', 'ff6666', 'ff3333', 'ff0000', 'ff3300',
'cc3300', 'ff6633', 'ff9966', '993300', 'cc6633', 'ff6600', 'cc9966', 'ff9933',
'663300', '996633', 'cc6600', 'ffcc99', 'ff9900', 'cc9933', '996600', 'ffcc66',
'cc9900', 'ffcc33', 'ffcc00', '333300', '666633', '666600', '999966', '999933',
'999900', 'cccc99', 'cccc66', 'cccc33', 'cccc00', 'ffffcc', 'ffff99', 'ffff66',
'ffff33', 'ffff00', 'ccff00', '99cc00', 'ccff33', '669900', '99cc33', 'ccff66',
'99ff00', '336600', '669933', '99cc66', '66cc00', 'ccff99', '99ff33', '66ff00',
'339900', '66cc33', '99ff66', '33cc00', '66ff33', '33ff00', '003300', '336633',
'006600', '669966', '339933', '009900', '99cc99', '66cc66', '33cc33', '00cc00',
'ccffcc', '99ff99', '66ff66', '33ff33', '00ff00', '00ff33', '00cc33', '33ff66',
'66ff99', '009933', '33cc66', '00ff66', '006633', '339966', '66cc99', '00cc66',
'99ffcc', '33ff99', '00ff99', '009966', '33cc99', '66ffcc', '00cc99', '33ffcc',
'00ffcc', '003333', '336666', '006666', '669999', '339999', '009999', '99cccc',
'66cccc', '33cccc', '00cccc', 'ccffff', '99ffff', '66ffff', '33ffff', '00ffff',
'00ccff', '0099cc', '33ccff', '006699', '66ccff', '3399cc', '0099ff', '003366',
'336699', '6699cc', '0066cc', '99ccff', '3399ff', '0066ff', '003399', '3366cc',
'6699ff', '0033cc', '3366ff', '0033ff', '000033', '333366', '000066', '666699',
'333399', '000099', '9999cc', '6666cc', '3333cc', '0000cc', 'ccccff', '9999ff',
'6666ff', '3333ff', '0000ff', '3300ff', '3300cc', '6633ff', '330099', '6633cc',
'9966ff', '6600ff', '330066', '663399', '9966cc', '6600cc', 'cc99ff', '9933ff',
'9900ff', '9933cc', '660099', 'cc66ff', '9900cc', 'cc33ff', 'cc00ff', '330033',
'663366', '660066', '996699', '993399', '990099', 'cc99cc', 'cc66cc', 'cc33cc',
'cc00cc', 'ffccff', 'ff99ff', 'ff66ff', 'ff33ff', 'ff00ff', 'ff00cc', 'cc0099',
'ff33cc', '990066', 'cc3399', 'ff66cc', 'ff0099', '660033', '993366', 'cc6699',
'cc0066', 'ff99cc', 'ff3399', 'ff0066', '990033', 'cc3366', 'ff6699', 'cc0033',
'ff3366', 'ff0033', '000000', '333333', '666666', '999999', 'cccccc', 'ffffff');
#
#   Colors that are too dark for black text.
#
my @toodark=(
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0,
1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0,
0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0);

my $pagebg = '999999';
my $borderfg = '666666';

my $q = new CGI;

my $href = $q->url(-absolute=>1);

my $bg = $q->param('keywords') ? $q->param('keywords') : $q->param('bg');
my $fg = $q->param('fg');
my $choose = $q->param('choose');

my $title;
my $section;

if (defined $bg) {
   $bg = check_color($bg);

   if (defined $fg) {
      $fg = check_color($fg);
      textpage($bg, $fg);
      exit 0;
   }
   $title = "Web Safe Color Combinations: Background #$bg";
}
elsif (defined $fg) {
   $fg = check_color($fg);
   $title = "Web Safe Color Combinations: Foreground #$fg";
}
elsif (defined $choose) {
   if ($choose eq 'fg') {
      $title = "Web Safe Color Combinations: Choose Foreground (Text) Color";
      $section = 'Foreground';
   }
   elsif ($choose eq 'bg') {
      $title = "Web Safe Color Combinations: Choose Background Color";
      $section = 'Background';
   }
   else {
      error('');
   }
}
else {
   $title = "Explore Web Safe Color Combinations";
   $section = 'Home';
   $choose = 'bg';
}

#
#  Build the page.
#
print	$q->header,
	$q->start_html(-title=>"$title", -bgcolor=>"#$pagebg"),
	$q->h1("$title");

if ($section eq 'Home') {
   preamble();
   print qq(<p><b>Choose a background color:</b><p>\n);
}
prtable($bg, $fg, $choose);

print $q->p;
navbar($section);
print $q->address($q->a({-href=>"/people/jsb/"}, "John Bazik"));
print $q->end_html;
#
#  Done
#

sub preamble {
   print qq(<blockquote>\n);

   print qq(There are 216 "web safe" colors.  These are the
	colors that look the same on a wide variety of platforms.
	Restricting your web page design to these colors ensures that
	all visitors to your site get the same experience.);

   print $q->p;

   print qq(It's easy to browse 216 colors.  But web designers must
	choose color combinations.  There are 216<sup>2</sup> = 46656
	two-color, web-safe color combinations.  This page lets
	you explore those combinations as text (foreground) on
	background, rendered by your browser exactly as it would be in
	your web page.);

   print qq(</blockquote>\n);
}

sub prtable {
   my $bg = shift;
   my $fg = shift;
   my $choose = shift;
   my ($i);

   print qq(<table border="1" bordercolor="#$borderfg" bgcolor="#$pagebg"
							width=100%>\n);
   print qq(<tr align=center valign=top>);
   for $i (0..215) {
      if ($i && $i % 8 == 0) {
         print qq(</tr><tr align=center valign=top>\n);
      }
      prentry($i, $bg, $fg, $choose);
   }
   print qq(</tr>\n);
   print qq(</table>\n);
}

sub prentry {
   my $i = shift;
   my $bg = shift;
   my $fg = shift;
   my $choose = shift;

   if (defined $bg) {
      print	qq(<td><a href="$href?bg=$bg&fg=$webcols[$i]">-></a></td>\n);
      print	qq(<td bgcolor="#$bg">),
		qq(<font color="#$webcols[$i]">#$webcols[$i]</font></td>\n);
   }
   elsif (defined $fg) {
      print	qq(<td><a href="$href?bg=$webcols[$i]&fg=$fg">-></a></td>\n);
		qq(</a></td>\n);
      print	qq(<td bgcolor="#$webcols[$i]">),
		qq(<font color="#$fg">#$webcols[$i]</font></td>\n);
   }
   elsif (defined $choose) {
      print qq(<td><a href="$href?$choose=$webcols[$i]">-></a></td>\n);
      if ($toodark[$i]) {
         print	qq(<td bgcolor="#$webcols[$i]">),
		qq(<font color="#ffffff">#$webcols[$i]</font></td>\n);
      }
      else {
         print qq(<td bgcolor="#$webcols[$i]">#$webcols[$i]</td>\n);
      }
   }
}

sub textpage {
   my $bg = shift;
   my $fg = shift;
   my $title = "Web Safe Color Combinations: Foreground #$fg, Background #$bg";
   my $tcol;

   for ($i=0; $i<216; $i++) {
      if ($webcols[$i] eq $bg) {
         $tcol = $toodark[$i] ? "ffffff": "000000";
         last;
      }
   }
   print	$q->header,
		$q->start_html(	-title=>"$title",
				-text=>"#$fg",
				-link=>"#$tcol",
				-alink=>"#$tcol",
				-vlink=>"#$tcol",
				-bgcolor=>"#$bg"),
		$q->h1($q->font({-color=>"#$tcol"}, "$title"));

   print $q->h2("Of the origin and design of government in general,",
	"with concise remarks on the English Constitution.");

   print qq(Some writers have so confounded society with government, as
	to leave little or no distinction between them; whereas they
	are not only different, but have different origins. Society is
	produced by our wants, and government by wickedness; the former
	promotes our happiness positively by uniting our affections,
	the latter negatively by restraining our vices. The one
	encourages intercourse, the other creates distinctions. The
	first is a patron, the last a punisher.),

	$q->p,

	qq(Society in every state is a blessing, but government even in
	its best state is but a necessary evil; in its worst state an
	intolerable one; for when we suffer, or are exposed to the same
	miseries by a government, which we might expect in a country
	without government, our calamity is heightened by reflecting
	that we furnish the means by which we suffer. Government, like
	dress, is the badge of lost innocence; the palaces of kings are
	built on the ruins of the bowers of paradise. For were the
	impulses of conscience clear, uniform, and irresistibly obeyed,
	man would need no other lawgiver; but that not being the case,
	he finds it necessary to surrender up a part of his property to
	furnish means for the protection of the rest; and this he is
	induced to do by the same prudence which in every other case
	advises him out of two evils to choose the least. Wherefore,
	security being the true design and end of government, it
	unanswerably follows that whatever form thereof appears most
	likely to ensure it to us, with the least expence and greatest
	benefit, is preferable to all others.),

	$q->p,

	qq(In order to gain a clear and just idea of the design and end
	of government, let us suppose a small number of persons settled
	in some sequestered part of the earth, unconnected with the
	rest, they will then represent the first peopling of any
	country, or of the world. In this state of natural liberty,
	society will be their first thought.  A thousand motives will
	excite them thereto, the strength of one man is so unequal to
	his wants, and his mind so unfitted for perpetual solitude,
	that he is soon obliged to seek assistance and relief of
	another, who in his turn requires the same. Four or five united
	would be able to raise a tolerable dwelling in the midst of a
	wilderness, but one man might labour out the common period of
	life without accomplishing any thing; when he had felled his
	timber he could not remove it, nor erect it after it was
	removed; hunger in the mean time would urge him from his work,
	and every different want call him a different way. Disease, nay
	even misfortune would be death, for though neither might be
	mortal, yet either would disable him from living, and reduce
	him to a state in which he might rather be said to perish than
	to die.),

	$q->p,

	$q->font({-size=>"-1"}, "[from ", $q->em("Common Sense"),
		" by Thomas Paine]"),
	$q->p;

   navbar('');
   print $q->address($q->a({-href=>"/people/jsb/"}, "John Bazik"));
   print $q->end_html;
}

sub navbar {
   my $section = shift;

   print qq(<center>\n),
	$section eq 'Home' ? "&nbsp;Home&nbsp;" :
				qq(<a href="$href">[Home]</a>),
	qq(&nbsp;&nbsp;),
	$section eq 'Background' ? "&nbsp;Background&nbsp;" :
				qq(<a href="$href?choose=bg">[Background]</a>),
	qq(&nbsp;&nbsp;),
	$section eq 'Foreground' ? "&nbsp;Foreground&nbsp;" :
				qq(<a href="$href?choose=fg">[Foreground]</a>),
	qq(\n</center>\n);
}

sub check_color {
   my $color = shift;

   $color =~ /^#?([0-9a-fA-F]{6})$/ || error($color);

   return $1;
}

sub error {
	my $color = shift;

	print $q->header;
	print $q->start_html(	-title=>'Error');
	print $q->h1("Error");
	print "Bad color specification: $color\n";
	print $q->end_html;
	exit 0;
}
