cv.pl

#!/usr/bin/perl

################################################################################
#
#   Resume builder
#
#   This perl script generates a resume.  The basic idea is to separate the
#   format from the content.  In this script, the content is at the top, and
#   the format is in the functions in the bottom.  This makes it pretty easy
#   to work on the wording in one pass, and then go back and change what it
#   all looks like in a second pass.
#
#   To generate the resume, type "perl cv.pl".  This will create three files.
#   (1) a normal HTML file, (2) a "printable" HTML file (less color and
#   formatting) and (3) a plain text file.
#
#   To change the appearance, you'll need to change the functions at the bottom.
#   Most of them are straightforward, but a few of them (like bullets) need a
#   special "start bullets" function and an "end bullets" function to make sure
#   the proper HTML tags are inserted in the lists, etc.
#
#   Of course, the more you customize, you might end up changing some of the
#   functions to accept more or fewer parameters.  start_main() is a good
#   example of this.  I wanted my name and address followed by my phone number
#   and email address.  You might want more or fewer things.
#
#   Notice that sometimes, I choose to put the formatting in the "content" area.
#   In special cases, I want to emphasize something in particular.  Here's a
#   good example.
#
#   plain_item("Availability: <FONT COLOR=CE0000>not currently looking</FONT>.");
#
################################################################################

# START

# CONFIGURE HERE

$normal_html_filename="index.html";
$printable_html_filename="porter.html";
$plain_text_filename="porter.txt";
$text_width=72;
$font_sans_serif="Arial,Helvetica";

# INITIALIZE OUTPUT FILES AND VARIOUS VARIABLES

initialize();

# START OF RESUME CONTENT HERE

###  T I T L E  ################################################################

start_main("Alan Porter",
 "611 Park York Lane, Cary NC 27519",
 "porter611\@kr4jb.net", "(919) 386-9188");

###  S U M M A R Y  ############################################################

start_section("SUMMARY");
 plain_item(""
  ."Embedded software engineer and mobile applications developer. "
  ."Linux desktop user since 1992. "
  ."Pioneer in embedded Linux, also familiar with RTOS's. "
  ."Published iPhone application developer. "
  ."Expert level C and C++, comfortable with Python and Perl. "
  ."Familiar with Web 2.0 (PHP, Javascript, CSS). "
  ."Interest in security and common-sense usability. "
  ."Team player or individual contributor. "
  ."Articulate, explains complex ideas well. "
  ."International experience.");
  #."Modern day Renaissance Man. "
  #."Emphasis on real-time embedded systems and Unix/Linux server systems. "
  #."operating system internals, "
  #."reliability, "
  #."software/hardware interface. "
  #."Interests in wireless communications, "
end_section();

plain_item("");
plain_item("NOTE - jobs are not listed in chronological order.");
plain_item("");

###  E M B E D D E D   S O F T W A R E  ########################################

start_section("EXPERIENCE - MOBILE AND EMBEDDED SOFTWARE");

 # ---  T M I O  ---

 work("TMIO","Research Triangle Park NC","Software Engineer, Embedded Linux System Designer",
  "February 2004 to October 2006","http://www.tmio.com","logo_tmio.gif");

 start_bullets();

  titled_bullet("Start-up Company",
   "First employee at software development office in RTP. "
   ."Active in product planning and technology evaluation. "
   ."System administrator duties included network planning, DHCP, DNS, internet domains, "
   ."VPN, internal email, source code control (subversion), printers, automated backups.");

  titled_bullet("Embedded Linux System",
   "Created a custom Linux distribution to run on a single-board computer with limited resources. "
   ."Selected open source packages and organized them them into a repeatable build process. "
   ."Wrote device drivers for custom hardware. "
   ."Provided run-time platform for other developers.");

  titled_bullet("C++ Appliance Control Software",
   "Wrote custom software in C++ to control an \"Intelligent\" oven appliance. "
   ."Interfaced with several open source libraries (log4c++, Xerces XML, SQLite). "
   ."Developed XML protocol that client applications use to control the oven.");

  titled_bullet("Security Analysis",
   "Evaluated the security of the product design, "
   ."both for the oven in the home and for the back-end servers.");

 end_bullets();

mid_section();

 # ---  E R I C S S O N   A N D   S O N Y   E R I C S S O N  ---

 work("Ericsson","Research Triangle Park NC","Embedded Software Engineer",
  "March 1998 to March 2003","http://www.ericsson.com","logo_ericsson.gif");

 start_bullets();

  titled_bullet("Cellular Phone Software",
   "Wrote embedded software (in C, assembly) for mainstream cellular phone products. "
   ."Added support for camera accessory and high speed data services to "
   ."<a href=\"ericsson.html#central\">CDMA phones</a> (Sprint, Verizon). "
   ."Wrote device drivers and protocol software for a GSM-based "
   ."<a href=\"ericsson.html#athena\">FM radio phone</a>, shown at CeBit-99. "
   ."Developed over-the-air instant messaging protocol for a "
   ."<a href=\"ericsson.html#julia\">concept phone for teenagers</a>.");

  titled_bullet("Ericsson Cyberlab ".country("Singapore")." (16 months)",
   "Built prototype gadgets to visualize and test "
   ."<a href=\"ericsson.html#uhura\">3G application concepts</a> "
   ."and "
   ."<a href=\"ericsson.html#nanocube\">home network services</a>. "
   ."Test results led to changes in mainstream product designs. "
   ."Team leader for the prototyping group (three engineers). "
   ."Created a <a href=\"ericsson.html#vt520\">phone simulator</a> "
   ."to test application flow in user trials.");

  titled_bullet("Special Assignment in ".country("Sweden")." (2 months)",
   "Served as liaison between development groups in the US and in Sweden. "
   ."Chosen for my ability to comprehend and explain wide technical problems. "
   ."Directed 3rd-party contractors in implementation of \"push\" feature for WAP mini-browser.");

  titled_bullet("Professional Training",
   "Completed technical courses on "
   ."Embedded Linux, Speech Recognition and Digital Signal Processing. "
   ."Attended <I>Leadership Core Curriculum</I> management training.");

 end_bullets();

mid_section();

 # ---  C H I C K W A Y  ---

 work("Chickway Systems","High Point NC","Senior Software Engineer",
  "May 1994 to October 1996","http://www.computerwayfoodsystems.com",
  "logo_chickway.gif");

 start_bullets();

  titled_bullet("CTS-6000 Touch Screen",
   "Project leader and primary developer for CTS-6000 industrial weighing and labeling station. "
   ."Developed long-term project goals and "
   ."managed (sometimes conflicting) requirements. "
   ."Designed user interface for industrial usability. "
   ."Wrote entire embedded software package in C++, including "
   ."a cooperative multi-tasking scheduler, "
   ."a TCP/IP network interface, "
   ."and a reliable data storage system.");

  titled_bullet("Unix-based Inventory Management System",
   "Led the design of Computerway bar-code scanning system. "
   ."Wrote inventory management software that is used in a warehouse environment. "
   ."Developed custom software for wireless handheld bar-code scanners. "
   ."Created database tables using the Sculptor data modeling tools.");

  titled_bullet("Customer Interaction",
   "Installed and supported CTS-6000 touch screens "
   ."in working poultry processing plants. "
   ."Supported sales team on pre-sales plant visits.");

 end_bullets();

end_section();

print_html_paper("<BR><BR>");

###  U N I X   S E R V E R   S O F T W A R E  ##################################

start_section("EXPERIENCE - UNIX SERVER SOFTWARE");

 # ---  T E K E L E C  ---

 work("Tekelec","Research Triangle Park NC",
  "Software Engineer","October 2006 to present",
  "http://www.tekelec.com","logo_tekelec.png");

 start_bullets();

  titled_bullet("Enterprise Linux Distribution",
   "Supported and made enhancements to Tekelec's RHEL-based Enterprise Linux distribution. "
   ."Added new capabilities to internal build tools. "
   ."Supported high-availability features for telecom-grade usage.");

  titled_bullet("Web Application Development",
   "Wrote PHP and Javascript code to launch and monitor system software upgrades. "
   ."Worked with Zend framework and Dojo UI widgets. "
   ."Contributed to Linux-based high-availability cluster that is used for nation-wide cellular call routing (HLR).");

  titled_bullet("Security Analysis",
   "Hardened Tekelec's platform software for approval by US Military (DISA).");

 end_bullets();

mid_section();

 # ---  A 4   H E A L T H   S Y S T E M S  ---

 work("A4 Health Systems","Cary NC",
  "Graduate Student / Software Engineer","October 1996 to December 1997",
  "http://www.a4healthsystems.com","logo_a4.gif");

 start_bullets();

  titled_bullet("Unix Back-End Server Processes",
   "Re-engineered unix server processes for enVista Document Manager product. "
   ."Increased system reliability, automated the installation process and cut maintenance costs. "
   ."Instituted a version control system for back-end programs, scripts and data files. "
   ."Used Oracle and Sybase SQL.");

  titled_bullet("Formal and Informal Training",
   "Taught in-house classes on unix and client-server technology. "
   ."Performed customer-site installations and training.");

 end_bullets();

mid_section();

 # ---  G E   F A N U C  ---

 work("General Electric","Charlottesville VA",
  "Software Engineering Contractor","January 1993 to May 1994",
  "http://www.gefanuc.com","logo_ge_fanuc.gif");

 start_bullets();

  titled_bullet("Unix/PLC Communication Protocols",
   "Designed and implemented an ethernet communication bridge between "
   ."a unix workstation and GE Fanuc's Programmable Logic Controllers.");

 end_bullets();

mid_section();

 # ---  N O R T E L  ---

 work("Nortel","Research Triangle Park NC","Software Engineer",
  "August 1991 to January 1993","http://www.nortel.com","logo_nortel.gif");

 start_bullets();

  titled_bullet("Unix Tools",
   "Developed unix-based version control and software development tools "
   ."for the Network Services Division.");

  titled_bullet("Special Assignment in "
   .country("Maidenhead, England")." (6 months)",
   "Performed sanity tests and feature tests on "
   ."international telephone gateway switch.");

 end_bullets();

end_section();

###  S K I L L S  ##############################################################

#start_table_section("SKILLS");
#
# table_item("Languages","English","Chinese");
# table_item("Processors","Motorola M68HC11","AVR","PIC","BASIC Stamp");
# table_item("Useless knowledge","FORTRAN","BASIC","Action!","Sculptor");
#
#end_table_section();

###  E D U C A T I O N  ########################################################

start_section("EDUCATION");

 # ---  N C   S T A T E   U N I V E R S I T Y  ---

 work("North Carolina State University", "Raleigh NC",
  "Master of Computer Science","January 1997 to December 2000",
  "http://www.ncsu.edu","logo_ncsu.gif");

 start_bullets();

  bullet("Courses of interest: "
   ."Real Time Systems, "
   ."Network Security, "
   ."Wireless Communication, "
   ."Human Computer Interaction.");

  dated_bullet("December 2000","Master of Computer Science degree.");

  dated_bullet("May 1991","Bachelors degree in Mechanical Engineering, Computer Science Minor.");

 end_bullets();

end_section();

###  A C T I V I T I E S   A N D   I N T E R E S T S  ##########################

start_section("ACTIVITIES AND INTERESTS");

 start_bullets();

  bullet("Active member of the "
    ."<A HREF=\"http://TriLUG.org\">Triangle Linux User's Group</A>. "
    ."Steering Committee member in 2008, Chair in 2009.");

  bullet("Active member and occasional speaker for the "
    ."<A HREF=\"http://ieee-embedded.org\">IEEE Embedded Systems interest group</A>.");

  bullet("Elected 2004 president of the "
   ."<A HREF=\"http://TriangleAmateurRobotics.org\"> Triangle Amateur Robotics club</A>. "
   ."Organizer and presenter. Volunteer judge for First Lego League.");

  bullet("Published an iPhone app called \"Tipster\", "
   ."available through Apple iTunes.");

  bullet("Wrote a Real Time Operating System (RTOS) "
   ."called \"Presto\" for Motorola 68HC11 and Atmel AVR.");

  bullet("Publication: \"Multitasking on the Cheap\", "
   ."<I>Dr Dobb's Journal</I>, February 2004. "
   ."A simple way to implement multiple program threads by using a cooperative scheduler.");

  bullet("Attended security conferences: <A HREF=\"http://CarolinaCon.org\">CarolinaCon</A> (Chapel Hill) and "
   ."<A HREF=\"http://conference.hackinthebox.org/hitbsecconf2009kl/\">Hack In The Box</A> (Kuala Lumpur).");

  bullet("Two years' study of Mandarin Chinese language.");

  bullet("Amateur radio operator.  Extra class license, callsign KR4JB.");

  bullet("Private pilot (September 2006).  "
    ."Member of the <A HREF=\"http://WingsOfCarolina.org\"> Wings of Carolina flying club</A>.");

 end_bullets();

end_section();

###  C L O S I N G  ############################################################

closing("http://AlanPorter.com/resume","updated $date");

end_main();

###  C L E A N   U P  ##########################################################

print("\n");
print("Produced three output files:\n");
print(" - normal HTML: $normal_html_filename\n");
print(" - printable:   $printable_html_filename\n");
print(" - plain text:  $plain_text_filename\n");
print("\n");

cleanup();
exit;

################################################################################
#   EVERYTHING ABOVE THIS LINE IS CONTENT
#   EVERYTHING BELOW THIS LINE IS FORMAT
################################################################################
#   TOP / BOTTOM
################################################################################

sub start_main {
   my ($name,@lines)=@_;

   # HTML OUTPUT
   print_html("<!-- start_main -->\n");
   print_html("<HTML>\n");
   print_html("<HEAD>\n");
   print_html("<TITLE>R&eacute;sum&eacute; - $name</TITLE>\n");
   print_html("</HEAD>\n");

   #print_html("<style type=text/css>\n");
   #print_html("<!--\n");
   #print_html("a:link{color:#C00; text-decoration: none;}\n");
   #print_html("a:visited{color:#C00; text-decoration: none;}\n");
   #print_html("a:hover{color:#D00;}\n");
   #print_html("body{background-color:#000000;color:#000000;margin:8px;}\n");
   #print_html("-->\n");
   #print_html("</style>\n");

   print_html("<BODY"); # continued below
   print_html_normal(" BGCOLOR=C0C0C0");
   print_html_normal(" LINK=800000 VLINK=800000 ALINK=808080");
   print_html(">\n");
   print_html("<CENTER>\n");
   print_html("<FONT FACE=$font_sans_serif>\n");
   print_html("<FONT SIZE=+2><B>$name</B></FONT><BR>\n");
   foreach $line (@lines) {
      # avoid spam by encoding lines which contain email addresses
      my $coded_line=codify($line);
      print_html("$coded_line<BR>\n");
   }
   print_html("</FONT>\n");
   print_html("</CENTER>\n");
   print_html("<BR>\n");
   print_html("\n");

   # TEXT OUTPUT
   print_centered_text(massage_text($name));
   foreach $line (@lines) {
      print_centered_text(massage_text($line));
   }
   print_html("</FONT>\n");

}

################################################################################

sub end_main {

   # HTML OUTPUT
   print_html("<!-- end_main -->\n");
   print_html("</BODY>\n");
   print_html("</HTML>\n");
   print_html("\n");

   # TEXT OUTPUT
   print_text("");
}

################################################################################

sub closing {
   my @lines=@_;

   # HTML OUTPUT
   print_html("<!-- closing -->\n");
   print_html("<CENTER><FONT FACE=$font_sans_serif SIZE=-2><I>\n");
   foreach $line (@lines) {
      print_html("$line<BR>\n");
   }
   print_html("</I></FONT></CENTER>\n");
   print_html("\n");

   # TEXT OUTPUT
   print_text("");
   print_text("-" x $text_width);
   print_text("");
   foreach $line (@lines) {
      print_centered_text(massage_text($line));
   }
   print_text("");
}

################################################################################
#   MAJOR SECTIONS
################################################################################

sub start_section {
   my ($title)=@_;

   # HTML OUTPUT
   print_html("<!-- start_section -->\n");
   print_html("<CENTER>\n");

   # on web, page should span 95% of screen width (leave some dark margins)
   print_html_normal("<TABLE WIDTH=95% BORDER=0 CELLPADDING=5 CELLSPACING=3>\n");

   # on paper, use 100% of the paper width (let printer handle margins)
   print_html_paper("<TABLE WIDTH=100% BORDER=0 CELLPADDING=0 CELLSPACING=0>\n");

   # on web, a yellow rectangle with left-justified text
   print_html_normal("<TR BGCOLOR=EEEE99><TD>\n");  # yellow
   print_html_normal("<FONT FACE=$font_sans_serif>\n");
   print_html_normal("<B>$title</B>\n");
   print_html_normal("</FONT>\n");

   # on paper, a smaller table containing (short grey bar + text + long grey bar)
   print_html_paper("<TR><TD>\n");
   print_html_paper("<TABLE BORDER=0 WIDTH=100%><TR>");
   print_html_paper("<TD WIDTH=1% VALIGN=CENTER>");
   print_html_paper("<IMG SRC=\"pixel_grey192.gif\" BORDER=0 WIDTH=12 HEIGHT=12>");
   print_html_paper("</TD>");
   print_html_paper("<TD WIDTH=1% VALIGN=CENTER>");
   print_html_paper("<FONT FACE=$font_sans_serif>\n");
   print_html_paper("<B><NOBR>$title</NOBR></B>\n");
   print_html_paper("</FONT>\n");
   print_html_paper("</TD>");
   print_html_paper("<TD WIDTH=98% VALIGN=CENTER>");
   print_html_paper("<IMG SRC=\"pixel_grey192.gif\" BORDER=0 WIDTH=100% HEIGHT=12>");
   print_html_paper("</TD>");
   print_html_paper("</TR></TABLE>");
   print_html_paper("<IMG SRC=\"pixel_clear.gif\" BORDER=0 WIDTH=8 HEIGHT=8>");

   # same as mid-section
   print_html("</TD></TR>\n");
   print_html("<TR");
   print_html_normal(" BGCOLOR=F0F0F0");  # very light grey
   print_html("><TD>\n");
   print_html("\n");

   # TEXT OUTPUT
   print_text("");
   print_text("-" x $text_width);
   print_text("");
   print_text("[$title]");
   print_text("");

}

################################################################################

sub mid_section {

   # HTML OUTPUT
   print_html("<!-- mid_section -->\n");
   print_html("</TD></TR>\n");

   # paper version should have a light line here
   print_html_paper("<TR HEIGHT=14><TD></TD></TR>\n");
   print_html_paper("<TR HEIGHT=1><TD>");
   print_html_paper("<IMG SRC=\"pixel_grey224.gif\" WIDTH=100% HEIGHT=1>");
   print_html_paper("</TD></TR>\n");
   print_html_paper("<TR HEIGHT=8><TD></TD></TR>\n");

   print_html_normal("<TR BGCOLOR=F0F0F0><TD>\n");  # very light grey
   print_html_paper("<TR><TD>\n");
   print_html("\n");

   # TEXT OUTPUT
   print_text("");
}

################################################################################

sub end_section {

   # HTML OUTPUT
   print_html("<!-- end_section -->\n");
   print_html("</TD></TR>\n");
   print_html("</TABLE>\n");
   print_html("</CENTER>\n");
   print_html("<BR>\n");
   print_html("\n");

   # TEXT OUTPUT
   #print_text("");
   #print_text("2" x $text_width);
   #print_text("");
}

################################################################################
#   TABLES
################################################################################

sub start_table_section {
   my ($title,@columns)=@_;

   $table_title=$title;
   @table_headers=();
   @table_details=();      # a list of lists, see pg 257 of perl book

   # HTML OUTPUT
   print_html("<!-- start_table_section -->\n");
   print_html("\n");

   # TEXT OUTPUT
   print_text("");
   print_text("-" x $text_width);
   print_text("");
   print_text("[$title]");
   print_text("");
}

################################################################################

sub table_item {
   my @details=@_;
   my $header=shift @details;  # the first one is the title

   push(@table_headers,$header);
   push(@table_details,[@details]);

   # NO HTML OUTPUT
   # NO TEXT OUTPUT
}

################################################################################

sub end_table_section {

   my $i;
   my $j;

   # HTML OUTPUT
   print_html("<!-- end_table_section -->\n");
   print_html("<CENTER>\n");
   print_html_normal("<TABLE WIDTH=95% BORDER=0 CELLPADDING=5 CELLSPACING=3>\n");
   print_html_paper("<TABLE WIDTH=95% BORDER=0 CELLPADDING=5 CELLSPACING=3>\n");
   # the title row has a large row-span
   print_html("<TR");
   print_html_normal(" BGCOLOR=EEEE99");
   my $span=$#table_headers+1;
   print_html("><TD COLSPAN=$span>\n");
   print_html("<FONT FACE=$font_sans_serif>\n");
   print_html("<B>$table_title</B>\n");
   print_html("</FONT>\n");
   print_html("</TD></TR>\n");
   # the "table headers" row
   print_html("<TR");
   print_html_normal(" BGCOLOR=F0F0F0");
   print_html("><TD>\n");
   foreach $i (0..$#table_headers) {
      if($i>0) {
         print_html("<TD>");
      }
      print_html("<FONT FACE=$font_sans_serif>\n");
      print_html("$table_headers[$i]</TD>\n");
      print_html("</FONT>\n");
   }
   print_html("</TR>\n");
   # one row of details
   print_html("<TR");
   print_html_normal(" BGCOLOR=F0F0F0");
   print_html(">\n");
   # begin detail columns
   for $i (0..$#table_details) {
      print_html("<TD VALIGN=TOP>");
      for $j (0..$#{$table_details[$i]}) {
         print_html("<FONT FACE=$font_sans_serif>\n");
         print_html("$table_details[$i][$j]<br>\n");
         print_html("</FONT>\n");
      }
      print_html("</TD>");
   }
   print_html("</TR>\n");
   print_html("</TABLE>\n");
   print_html("</CENTER>\n");
   print_html("<BR>\n");
   print_html("<BR>\n");
   print_html("\n");

   # TEXT OUTPUT
   for $i (0..$#table_details) {
      my $line="$table_headers[$i]: ".$table_details[$i][0];
      for $j (1..$#{$table_details[$i]}) {
         $line=$line.", ".$table_details[$i][$j];
      }
      $line=massage_text($line);
      print_text($line,3);
   }
}

################################################################################
#   MAJOR ITEMS WITHIN A SECTION
################################################################################

sub work {
   my ($company,$city,$title,$dates,$url,$pic)=@_;

   # HTML OUTPUT
   print_html("<!-- work -->\n");
   print_html("<TABLE BORDER=0 WIDTH=100%><TR>\n");
   print_html("<TD ALIGN=LEFT>\n");
   print_html("<FONT COLOR=800000 FACE=$font_sans_serif>\n");
   #print_html("<FONT SIZE=+1>\n");
   print_html("<B>");
   print_html_normal("<A HREF=\"$url\">");
   print_html("$company");
   print_html_normal("</A>");
   print_html("</B>, $city<BR>\n");
   #print_html("</FONT>\n");
   print_html("<FONT SIZE=-1>\n");
   if(length($title)>0) {
      print_html("$title<BR>\n");
   }
   print_html("$dates\n");
   print_html("</FONT>\n");
   print_html("</FONT>\n");
   print_html("</TD>\n");
   if($pic ne "") {
      print_html("<TD ALIGN=RIGHT>\n");
      print_html_normal("<A HREF=\"$url\">");
      print_html("<IMG SRC=\"$pic\" BORDER=0 BGCOLOR=FFFF00>");
      print_html_normal("</A>\n");
      print_html("</TD>\n");
   }
   print_html("</TABLE>\n");
   print_html("\n");

   print_html("<IMG SRC=\"pixel_clear.gif\" BORDER=0 WIDTH=6 HEIGHT=6><BR>");

   # TEXT OUTPUT
   print_text(massage_text($company).", ".massage_text($city));
   print_text(massage_text($title));
   print_text(massage_text($dates));
   print_text("");
}

################################################################################
#   BULLETS
################################################################################

sub start_bullets {

   # HTML OUTPUT
   print_html("<!-- start_bullets -->\n");
   print_html("<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0>\n");

   # NO TEXT OUTPUT

   # MISCELLANEOUS
   $bullet=0;
}

################################################################################

sub bullet {
   my ($text)=@_;
   my $withoutlinks=massage_text($text);

   # HTML OUTPUT
   print_html("<!-- bullet -->\n");
   print_html("<TR>\n");
   print_html("<TD VALIGN=TOP>&nbsp;&bull;&nbsp;</TD>\n");
   print_html("<TD>\n");
   print_html("<FONT FACE=$font_sans_serif SIZE=-1>\n");
   print_html_normal("$text\n");
   print_html_paper("$withoutlinks\n");
   print_html("</FONT>\n");
   print_html("</TD>\n");
   print_html("\n");

   # TEXT OUTPUT
   if($bullet > 0) { print_text(""); }
   $text=massage_text($text);
   print_text(" - $text",3);

   # MISCELLANEOUS
   $bullet++;
}

################################################################################

sub dated_bullet {
   my ($date,$text)=@_;
   my $withoutlinks=massage_text($text);

   # HTML OUTPUT
   print_html("<!-- bullet -->\n");
   print_html("<TR>\n");
   print_html("<TD VALIGN=TOP>&nbsp;&bull;&nbsp;</TD>\n");
   print_html("<TD>\n");
   print_html("<FONT FACE=$font_sans_serif SIZE=-1>\n");
   print_html_normal("<B>$date</B>: $text\n");
   print_html_paper("<B>$date</B>: $withoutlinks\n");
   print_html("</FONT>\n");
   print_html("</TD>\n");
   print_html("\n");

   # TEXT OUTPUT
   if($bullet > 0) { print_text(""); }
   $text=massage_text($text);
   print_text(" - $date: $text",3);

   # MISCELLANEOUS
   $bullet++;
}

################################################################################

sub titled_bullet {
   my ($header,$text)=@_;
   my $withoutlinks=massage_text($text);

   # HTML OUTPUT
   print_html("<!-- titled_bullet -->\n");
   if($bullet > 0) {
      print_html("<TR>\n");
      print_html("<TD COLSPAN=2>\n");
      print_html("<IMG SRC=\"pixel_clear.gif\" BORDER=0 WIDTH=6 HEIGHT=6>");
      print_html("</TD>\n");
      print_html("</TR>\n");
   }
   print_html("<TR>\n");
   print_html("<TD VALIGN=TOP>&nbsp;&bull;&nbsp;</TD>\n");
   print_html("<TD>\n");
   print_html("<FONT COLOR=006000 FACE=$font_sans_serif><B>$header</B></FONT><BR>\n");
   print_html("<FONT FACE=$font_sans_serif SIZE=-1>\n");
   print_html_normal("$text\n");
   print_html_paper("$withoutlinks\n");
   print_html("</FONT>");
   print_html("</TD>\n");
   print_html("\n");

   # TEXT OUTPUT
   if($bullet > 0) { print_text(""); }
   $header=massage_text($header);
   $header=toupper($header);
   print_text(" + $header",3);
   $text=massage_text($text);
   print_text("   $text",3);

   # MISCELLANEOUS
   $bullet++;
}

################################################################################

sub end_bullets {

   # HTML OUTPUT
   print_html("<!-- end_bullets -->\n");
   print_html("</TABLE>\n");
   print_html("\n");

   # NO TEXT OUTPUT
}

################################################################################
#   LISTS, ETC
################################################################################

sub simple_list {
   my @lines=@_;

   # HTML OUTPUT
   print_html("<!-- simple_list -->\n");
   print_html("<FONT FACE=$font_sans_serif>\n");
   foreach $line (@lines) {
      print_html("$line<BR>\n");
   }
   print_html("</FONT>\n");
   print_html("\n");

   # TEXT OUTPUT
   foreach $line (@lines) {
      print_text($line,3);
   }
   print_text("");
}

################################################################################

sub plain_item {
   my ($text)=@_;

   # HTML OUTPUT
   print_html("<!-- plain_item -->\n");
   print_html("<FONT FACE=$font_sans_serif>\n");
   print_html("$text<BR>\n");
   print_html("</FONT>\n");
   print_html("\n");

   # TEXT OUTPUT
   print_text(massage_text($text),0);
}

################################################################################
#   OTHER FORMATTING
################################################################################

sub country {
   my ($text)=@_;
   return "<FONT COLOR=004000>$text</FONT>";
   #return "$text";
}

################################################################################
#  EVERYTHING ABOVE THIS LINE IS FORMATTING
#  EVERYTHING BELOW THIS LINE IS INFRASTRUCTURE
################################################################################

sub initialize {
   # open output files
   unlink($normal_html_filename);
   unlink($printable_html_filename);
   unlink($plain_text_filename);

   open(NORMAL,">$normal_html_filename");
   open(PAPER,">$printable_html_filename");
   open(TEXT,">$plain_text_filename");
   # set some variables the user might want to use
   use POSIX qw(strftime);
   $date=strftime("%d %B %Y",localtime);
   $date=~s/^0//g;  # remove leading zero
   $time=strftime("%H:%M:%S",localtime);
   $time=~s/^0//g;  # remove leading zero
}

################################################################################

sub cleanup {
   close(NORMAL);
   close(PAPER);
   close(TEXT);
}

################################################################################
#   HTML MANIPULATION
################################################################################

sub print_html {
   my $line=$_[0];
   print NORMAL ($line);
   print PAPER ($line);
}

################################################################################

sub print_html_normal {
   my $line=$_[0];
   print NORMAL ($line);
}

################################################################################

sub print_html_paper {
   my $line=$_[0];
   print PAPER ($line);
}

################################################################################

sub codify {
   # Spammers often scrape web pages to find email addresses.
   # This function obscures email addresses and other strings
   # by printing them as ASCII values.
   my $input=$_[0];
   my $output="";
   my $x;
   for $x (0..(length($input)-1)) {
      $output=$output."&#".ord(substr($input,$x,1)).";";
   }
   return $output;
}

################################################################################
#   TEXT MANIPULATION
################################################################################

sub massage_text {
   my $text=$_[0];
   $text=~s/<[^>]*>//g;
   $text=~s/\n/ /g;
   $text=~s/ +/ /g;
   $text=~s/&amp;/&/g;
   return $text;
}

################################################################################

sub tolower {
   my $string=$_[0];
   $string=~tr/A-Z/a-z/;
   return $string;
}

################################################################################

sub toupper {
   my $string=$_[0];
   $string=~tr/a-z/A-Z/;
   return $string;
}

################################################################################

sub wrap_text {
   my $finished="";
   my $to_be_processed=$_[0];
   my $indent=$_[1];
   my $pos_in_string;

   while(length($to_be_processed)>$text_width) {
      $pos_in_string=$text_width;
      # find a good place to break the text
      while(substr($to_be_processed,$pos_in_string,1) ne " ") {
         $pos_in_string--;
      }
      if($pos_in_string>0) {
         # we can cut it at $pos_in_string
         $finished=$finished.substr($to_be_processed,0,$pos_in_string)."\n";
         $to_be_processed=" " x $indent . substr($to_be_processed,$pos_in_string+1);
      } else {
         # there was no good place to break it, so cut at $text_width
         $finished=$finished.substr($to_be_processed,0,$text_width)."\n";
         $to_be_processed=" " x $indent . substr($to_be_processed,$text_width);
      }
   }
   $finished=$finished.$to_be_processed;
   return $finished;
}

################################################################################

sub print_text {
   my $line=$_[0];
   my $indent=0;
   if($#_>0) { $indent=$_[1]; }
   $line=wrap_text($line,$indent);
   print TEXT ("$line\n");
}

################################################################################

sub print_centered_text {
   my $string=$_[0];
   $string=~s/\n//g;
   $string=~s/^ +//g;
   my $count=($text_width-length($string))/2;
   my $spaces= " " x $count;
   print TEXT ("$spaces$string\n");
}

################################################################################
################################################################################

# END