<?php

/* Calendar generator for Germany.
 * Written by Manuel Haim (see history below).
 * Feel free to use and alter this script. */

 /* Requires:
 * FPDF library, see http://www.fpdf.org/
 */
//define('FPDF_PHP', 'fpdf185/fpdf.php');
define('FPDF_PHP', 'fpdf.php');

/* Run main program. */
$kalender = new Kalender();
$kalender->create_year();
$kalender->draw();

/* History:
 *
 * 04-Feb-2008
 * -first version
 * -special days: Germany, its federal states, the protestant church
 *
 * 10-Feb-2008
 * -special days: the catholic church, start/end of summer time
 * -optimized $days array
 * -added getscript for PHP script download
 *
 * 17-Feb-2008
 * -caring about PHP Notices (doing some isset() stuff)
 *
 * 23-Mar-2016
 * -fixed $easter_date
 *
 * 02-Feb-2019
 * -updated 'ev' church year (epiphany ends with 02-Feb now)
 * 
 * 13-Apr-2023
 * -fixed class constructor for PHP 8 (function Kalender -> function __construct)
 * -added UTF-8 to windows-1252 conversion
 * -fixed getscript
 */

class Kalender
{
var $year;        // current year
var $orientation; // 'landscape' or 'portrait'
var $type;        // 'pdf_year'
var $de;          // e.g. 'true' or '1'
var $state;       // e.g. 'true' or '1' or 'nw'
var $ev;          // e.g. 'true' or '1'
var $kath;        // e.g. 'true' or '1'
var $download;    // e.g. 'true' or '1'

var $days;        //
var $pdf;         //

function __construct($year=null)
{
  /* Main program. */
  if(isset($_GET['getscript']) && $_GET['getscript']==true) { $this->getscript(); return; }
  if(isset($_GET['year'])) $this->year = $_GET['year']; // e.g. 2008
  if(isset($_GET['orientation'])) $this->orientation = $_GET['orientation']; // 'landscape' or 'portrait'
  if(isset($_GET['type'])) $this->type = $_GET['type']; // 'pdf_year' or 'html_year'
  if(isset($_GET['de'])) $this->de = $_GET['de']; // e.g. 'true' or '1'
  if(isset($_GET['state'])) $this->state = $_GET['state']; // e.g. 'true' or '1' or 'nw'
  if(isset($_GET['ev'])) $this->ev = $_GET['ev']; // e.g. 'true' or '1'
  if(isset($_GET['kath'])) $this->kath = $_GET['kath']; // e.g. 'true' or '1'
  if(isset($_GET['download'])) $this->download = $_GET['download']; // e.g. 'true' or '1'

  if (!isset($this->year) || $this->year == '') {
    $this->year = strftime("%Y");
  }

  if (isset($year)) {
    $this->year = $year;
  }

  if (!isset($this->orientation) || $this->orientation == '') {
    $this->orientation = 'portrait';
  }

  if(!isset($this->type) || $this->type == '') {
    $this->type = 'pdf_year';
  }

  if(!isset($this->de) || $this->de == '') {
    $this->de = false;
  }

  if(!isset($this->state) || $this->state == '') {
    $this->state = false;
  }

  if(!isset($this->ev) || $this->ev == '') {
    $this->ev = false;
  }

  if(!isset($this->kath) || $this->kath == '') {
    $this->kath = false;
  }

  if(!isset($this->download) || $this->download == '') {
    $this->download = false;
  }

  // if($this->year<1971 || $this->year>2037) return;
  $this->create_year();
}

function draw() {
  if($this->type=='pdf_year') {
    require(FPDF_PHP);
    if($this->orientation=='portrait') $this->draw_pdf_portrait();
    if($this->orientation=='landscape') $this->draw_pdf_landscape();
  } elseif($this->type=='html_year') {
    $this->draw_html();
  }
}

/* Jahr anlegen. */
function create_year() {
  //global $year;
  //global $days;

  // Quellen:
  // kath. Kirchenjahr: http://www.festjahr.de/festtage/chronologisch/index.html
  // ev. Kirchenjahr: http://www.kmf-info.de/liturgik.pdf
  //   2018/19: http://www.velkd.de/gottesdienst/lektionar-perikopenbuch.php
  // gesetzliche Feiertage: http://de.wikipedia.org/wiki/Feiertage_in_Deutschland

  // To do: Anfang von Fruehling, Sommer, Herbst, Winter
  // To do: Liturgische Farben der Feiertage des Kirchenjahres

  $this->days = array();

  // $easter_date_unix = easter_date($year);
  // Obige Zeile liefert nach Konvertierung mit getdate() ggf. ein falsches Datum,
  // siehe http://php.net/manual/de/function.easter-date.php

  // Zuverlässiger funktioniert es mit dieser Zeile:
  $easter_date_unix = strtotime($this->year."-03-21 +".easter_days($this->year)." days");
  $easter_date = getdate($easter_date_unix);
  $easter_yday = $easter_date['yday'];

  // Hier werden die Feiertage fuer Bund, Laender und Kirchen definiert.
  // Handelt es sich um gesetzliche Feiertage,
  // so erfolgt die Angabe in Grossbuchstaben, sonst klein:
  //
  // de = Deutschland
  // bb = Brandenburg
  // be = Berlin
  // bw = Baden-Wuerttemberg
  // by = Bayern
  // hb = Bremen
  // hh = Hamburg
  // he = Hessen
  // mv = Mecklenburg-Vorpommern
  // ni = Niedersachsen
  // nw = Nordrhein-Westfalen
  // rp = Rheinland-Pfalz
  // sl = Saarland
  // sn = Sachsen
  // st = Sachsen-Anhalt
  // sh = Schleswig-Holstein
  // th = Thueringen
  // ev = evangelische Kirche
  // kath = katholische Kirche

  // Deutschlandweit begangene Tage
  $this->add_desc( $this->get_yday(14,2), 'Valentinstag', array('de') );
  $this->add_desc( $this->get_yday(1,5), 'Maifeiertag ', array('DE') ); // auch: Tag der Arbeit

  // 2. Sonntag im Mai = Muttertag
  $may_date = getdate(mktime(0,0,0,5,0,$this->year)); // Tag vor dem 1.Mai
  $this->add_desc( $this->get_yday(14-$may_date['wday'],5), 'Muttertag', array('de') );

  $this->add_desc( $this->get_yday(3,10), 'Tag der Dt. Einheit', array('DE') );

  //add_desc( $easter_yday-52, 'Weiberfastnacht', array('de') );
  $this->add_desc( $easter_yday-48, 'Rosenmontag', array('de') );
  $this->add_desc( $easter_yday-47, 'Fastnacht', array('de','kath') );

  // Letzter Sonntag im Maerz = Beginn der Sommerzeit
  $month_days = date('t',mktime(0,0,0,3,1,$this->year));
  $march_date = getdate(mktime(0,0,0,3,$month_days,$this->year)); // Letzter Tag im Maerz
  $this->add_desc( $march_date['yday']-$march_date['wday'], 'Beginn d.Sommerzeit', array('de') );
  // Letzter Sonntag im Oktober = Ende der Sommerzeit
  $month_days = date('t',mktime(0,0,0,10,1,$this->year));
  $october_date = getdate(mktime(0,0,0,10,$month_days,$this->year)); // Letzter Tag im Oktober
  $this->add_desc( $october_date['yday']-$october_date['wday'], 'Ende der Sommerzeit', array('de') );


  // Kirchenjahr ab 01.01.:
  $this->add_desc( $this->get_yday(1,1), 'Gottesmutter Maria', array('kath') );
  $this->add_desc( $this->get_yday(1,1), 'Neujahr', array('DE','ev','kath') );

  $this->add_desc( $this->get_yday(6,1), 'Heilige Drei Könige', array('de','kath','BW','BY','ST') );
  $this->add_desc( $this->get_yday(6,1), 'Epiphanias', array('ev') );
  $this->add_desc( $this->get_yday(6,1), 'Erscheinung d.Herrn', array('kath') );

  $this->add_desc( $this->get_yday(25,1), 'Bekehrung des Paulus', array('kath') );
  $this->add_desc( $this->get_yday(2,2), 'Darstellung des Herrn', array('kath') );
  $this->add_desc( $this->get_yday(14,2), 'Cyrill und Methodius', array('kath') );
  $this->add_desc( $this->get_yday(22,2), 'Kathedra Petri', array('kath') );
  $this->add_desc( $this->get_yday(24,2), 'Matthias', array('kath') );
  $this->add_desc( $this->get_yday(19,3), 'Josef', array('kath') );
  $this->add_desc( $this->get_yday(25,3), 'Verkündigung d.Herrn', array('kath') );

  // Sonntage nach Epiphanias:
  $epiphanias_date = getdate(mktime(0,0,0,1,6,$this->year));
  $epiphanias_wday = $epiphanias_date['wday'];
  $this->add_desc( 5+(7-$epiphanias_wday), 'Taufe des Herrn', array('kath') );
  for( $i=0; 5+(7-$epiphanias_wday)+$i*7 < $easter_yday-35; $i++) {
    $this->add_desc( 5+(7-$epiphanias_wday)+$i*7, ($i+1).'. So im Jahreskreis', array('kath') );
  }
  // Bis 2018: Anzahl Sonntage abhaengig von Osterdatum
  $epiphanias_last = $easter_yday-70;
  // Ab 2019: Anzahl Sonntage abhaengig von Lichtmess (02.02.)
  $lichtmess_date = getdate(mktime(0,0,0,2,2,$this->year));
  if( $this->year >= 2019 ) {
    $epiphanias_last = $lichtmess_date['yday'] - $lichtmess_date['wday'];
  }
  for( $i=0; 5+(7-$epiphanias_wday)+$i*7 < $epiphanias_last; $i++) {
    $this->add_desc( 5+(7-$epiphanias_wday)+$i*7, ($i+1).'. So nach Epiphanias', array('ev') );
  }
  if( $epiphanias_date['yday'] < $epiphanias_last ) {
    $this->add_desc( $epiphanias_last, 'Letzter So nach Ep.', array('ev') );
  }

  $this->add_desc( $this->get_yday(25,4), 'Markus', array('kath') );
  $this->add_desc( $this->get_yday(3,5), 'Philippus u.Jakobus', array('kath') );
  $this->add_desc( $this->get_yday(24,6), 'Johannistag', array('ev') );
  $this->add_desc( $this->get_yday(24,6), 'Geburt Johannes', array('kath') );
  $this->add_desc( $this->get_yday(29,6), 'Petrus und Paulus', array('kath') );
  $this->add_desc( $this->get_yday(2,7), 'Mariä Heimsuchung', array('kath') );
  $this->add_desc( $this->get_yday(3,7), 'Thomas', array('kath') );
  $this->add_desc( $this->get_yday(11,7), 'Benedikt von Nursia', array('kath') );
  $this->add_desc( $this->get_yday(25,7), 'Jakobus', array('kath') );
  $this->add_desc( $this->get_yday(6,8), 'Verklärung des Herrn', array('kath') );
  $this->add_desc( $this->get_yday(10,8), 'Laurentius', array('kath') );
  $this->add_desc( $this->get_yday(15,8), 'Mariä Himmelfahrt', array('de','kath','SL') );
  $this->add_desc( $this->get_yday(22,8), 'Maria Königin', array('kath') );
  $this->add_desc( $this->get_yday(24,8), 'Bartholomäus', array('kath') );
  $this->add_desc( $this->get_yday(8,9), 'Mariä Geburt', array('kath') );
  $this->add_desc( $this->get_yday(14,9), 'Kreuzerhöhung', array('kath') );
  $this->add_desc( $this->get_yday(15,9), 'Schmerzen Mariens', array('kath') );
  $this->add_desc( $this->get_yday(21,9), 'Matthäus', array('kath') );
  $this->add_desc( $this->get_yday(29,9), 'Michaelis', array('ev') );
  $this->add_desc( $this->get_yday(29,9), 'Michael,Gabr.,Raffael', array('kath') );
  $this->add_desc( $this->get_yday(7,10), 'Frau vom Rosenkranz', array('kath') );
  $this->add_desc( $this->get_yday(18,10), 'Lukas', array('kath') );
  $this->add_desc( $this->get_yday(28,10), 'Simon und Judas', array('kath') );
  $this->add_desc( $this->get_yday(31,10), 'Reformationsfest', array('de','ev','BB','MV','SN','ST','TH') );
  $this->add_desc( $this->get_yday(1,11), 'Allerheiligen', array('de','kath','BW','BY','NW','RP','SL') );
  $this->add_desc( $this->get_yday(2,11), 'Allerseelen', array('kath') );
  $this->add_desc( $this->get_yday(9,11), 'Weihe Lateranbasilika', array('kath') );
  $this->add_desc( $this->get_yday(11,11), 'Martinstag', array('de') );
  $this->add_desc( $this->get_yday(21,11), 'Frau in Jerusalem', array('kath') );
  $this->add_desc( $this->get_yday(30,11), 'Andreas', array('kath') );
  $this->add_desc( $this->get_yday(8,12), 'Jungfrau Maria', array('kath') );

  // Osterfestkreis:
  // Ab 2019: Vorpassion abhaengig von Lichtmess (02.02.)
  if( $this->year >= 2019 && $epiphanias_last < $easter_yday-77 ) {
    $this->add_desc( $easter_yday-77, '5. So v.d. Passion', array('ev') );
  }
  if( $this->year >= 2019 && $epiphanias_last < $easter_yday-70 ) {
    $this->add_desc( $easter_yday-70, '4. So v.d. Passion', array('ev') );
  }
  if( $this->year <= 2018 ||
      ( $this->year >= 2019 && $epiphanias_last < $easter_yday-63 ) ) {
    $this->add_desc( $easter_yday-63, 'Septuagesimä', array('ev') );
  }
  //$this->add_desc( $easter_yday-63, 'Circumdederunt', array('kath') );
  if( $this->year <= 2018 ||
      ( $this->year >= 2019 && $epiphanias_last < $easter_yday-56 ) ) {
    $this->add_desc( $easter_yday-56, 'Sexagesimä', array('ev') );
  }
  //$this->add_desc( $easter_yday-56, 'Exsurge', array('kath') );
  if( $this->year <= 2018 ||
      ( $this->year >= 2019 && $epiphanias_last < $easter_yday-49 ) ) {
    $this->add_desc( $easter_yday-49, 'Estomihi', array('ev') );
  }
  $this->add_desc( $easter_yday-46, 'Aschermittwoch', array('de','ev','kath') );
  $this->add_desc( $easter_yday-42, 'Invokavit', array('ev') );
  //$this->add_desc( $easter_yday-42, 'Invokabit', array('kath') );
  $this->add_desc( $easter_yday-42, '1. Fastensonntag', array('kath') );
  $this->add_desc( $easter_yday-35, 'Reminiszere', array('ev',) );
  $this->add_desc( $easter_yday-35, '2. Fastensonntag', array('kath') );
  $this->add_desc( $easter_yday-28, 'Okuli', array('ev') );
  $this->add_desc( $easter_yday-28, '3. Fastensonntag', array('kath') );
  $this->add_desc( $easter_yday-21, 'Lätare', array('ev') );
  $this->add_desc( $easter_yday-21, '4. Fastensonntag', array('kath') );
  $this->add_desc( $easter_yday-14, 'Judika', array('ev') );
  $this->add_desc( $easter_yday-14, 'Passionssonntag', array('kath') );
  $this->add_desc( $easter_yday-14, '5. Fastensonntag', array('kath') );
  $this->add_desc( $easter_yday-7, 'Palmsonntag', array('de','ev','kath') );
  $this->add_desc( $easter_yday-7, '2. Passionssonntag', array('kath') );
  $this->add_desc( $easter_yday-3, 'Gründonnerstag', array('de','ev','kath') );
  $this->add_desc( $easter_yday-2, 'Karfreitag', array('DE','ev','kath') );
  $this->add_desc( $easter_yday-1, 'Karsamstag', array('ev','kath') );
  $this->add_desc( $easter_yday, 'Ostersonntag', array('DE','ev','kath') );
  $this->add_desc( $easter_yday+1, 'Ostermontag', array('DE','ev','kath') );
  $this->add_desc( $easter_yday+7, 'Quasimodogeniti', array('ev') );
  $this->add_desc( $easter_yday+7, 'Weißer Sonntag', array('kath') );
  $this->add_desc( $easter_yday+14, 'Misericordias Domini', array('ev') );
  $this->add_desc( $easter_yday+14, '3.So d.Osterzeit', array('kath') );
  $this->add_desc( $easter_yday+21, 'Jubilate', array('ev') );
  $this->add_desc( $easter_yday+21, '4.So d.Osterzeit', array('kath') );
  $this->add_desc( $easter_yday+28, 'Kantate', array('ev') );
  $this->add_desc( $easter_yday+28, '5.So d.Osterzeit', array('kath') );
  $this->add_desc( $easter_yday+35, 'Rogate', array('ev') );
  //$this->add_desc( $easter_yday+35, 'Vocem jocundidatis', array('kath') );
  $this->add_desc( $easter_yday+35, '6.So d.Osterzeit', array('kath') );
  $this->add_desc( $easter_yday+39, 'Christi Himmelfahrt', array('DE','ev') );
  $this->add_desc( $easter_yday+42, 'Exaudi', array('ev') );
  $this->add_desc( $easter_yday+42, '7.So d.Osterzeit', array('kath') );
  $this->add_desc( $easter_yday+49, 'Pfingstsonntag', array('DE','ev','kath') );
  $this->add_desc( $easter_yday+50, 'Pfingstmontag', array('DE','ev','kath') );
  $this->add_desc( $easter_yday+56, 'Dreieinigkeitsfest', array('de') );
  $this->add_desc( $easter_yday+56, 'Trinitatis', array('ev') );
  $this->add_desc( $easter_yday+56, 'Dreifaltigkeitssonntag', array('kath') );
  $this->add_desc( $easter_yday+60, 'Fronleichnam', array('de','kath','BW','BY','HE','NW','RP','SL') );
  $this->add_desc( $easter_yday+68, 'Herz-Jesu-Fest', array('kath') );
  $this->add_desc( $easter_yday+74, 'Unbefl. Herz Mariä', array('kath') );

  // Erntedankfest am ersten Sonntag nach Michaelis (evangelisch):
  $michaelis_date = getdate(mktime(0,0,0,9,29,$this->year));
  $erntedank_ev_yday = $michaelis_date['yday']-$michaelis_date['wday']+7;

  // Erntedankfest am ersten Sonntag im Oktober (katholisch):
  $october_date = getdate(mktime(0,0,0,10,0,$this->year)); // Tag vor dem 1.Oktober
  $erntedank_kath_yday = $this->get_yday(7-$october_date['wday'],10);

  if($erntedank_ev_yday == $erntedank_kath_yday) {
    $this->add_desc( $erntedank_ev_yday, 'Erntedankfest', array('ev','kath') );
  } else {
    $this->add_desc( $erntedank_ev_yday, 'Erntedankfest', array('ev') );
    $this->add_desc( $erntedank_kath_yday, 'Erntedankfest', array('kath') );
  }

  // Sonntage nach Trinitatis (Anzahl abhaengig von Weihnachtsdatum):
  $xmas_date = getdate(mktime(0,0,0,12,24,$this->year));
  $xmas_wday = $xmas_date['wday'];
  $xmas_yday = $xmas_date['yday'];
  for($i=0;$easter_yday+63+$i*7 < $xmas_yday-$xmas_wday-42;$i++) {
    $this->add_desc( $easter_yday+63+$i*7, ($i+1).'. So nach Trinitatis', array('ev') );
  }

  // Ende des Kirchenjahres:
  $this->add_desc( $xmas_yday-$xmas_wday-42, 'Drittletzter Sonntag', array('ev') );
  $this->add_desc( $xmas_yday-$xmas_wday-35, 'Volkstrauertag', array('de','ev') );
  $this->add_desc( $xmas_yday-$xmas_wday-35, 'Vorletzter Sonntag', array('ev') );
  $this->add_desc( $xmas_yday-$xmas_wday-32, 'Buß- und Bettag', array('de','ev','SN') );
  $this->add_desc( $xmas_yday-$xmas_wday-28, 'Totensonntag', array('de','ev') );
  $this->add_desc( $xmas_yday-$xmas_wday-28, 'Ewigkeitssonntag', array('ev') );
  $this->add_desc( $xmas_yday-$xmas_wday-28, 'Letzter Sonntag', array('ev') );
  $this->add_desc( $xmas_yday-$xmas_wday-28, 'Christkönig', array('kath') );
  for($i=0;$easter_yday+70+$i*7 < $xmas_yday-$xmas_wday-21;$i++) {
    $this->add_desc( $easter_yday+70+$i*7, ($i+9).'. So im Jahreskreis', array('kath') );
  }

  // Anfang des naechsten Kirchenjahres:
  $this->add_desc( $xmas_yday-$xmas_wday-21, '1.Advent', array('de','ev','kath') );
  $this->add_desc( $xmas_yday-$xmas_wday-14, '2.Advent', array('de','ev','kath') );
  $this->add_desc( $xmas_yday-$xmas_wday-7, '3.Advent', array('de','ev','kath') );
  $this->add_desc( $xmas_yday-$xmas_wday, '4.Advent', array('de','ev','kath') );
  $this->add_desc( $this->get_yday(6, 12), 'Nikolaus', array('de') );
  $this->add_desc( $this->get_yday(24, 12), 'Heiligabend', array('de','ev','kath') );
  $this->add_desc( $this->get_yday(25, 12), 'Geburt des Herrn', array('kath') );
  $this->add_desc( $this->get_yday(25, 12), '1. Weihnachtstag', array('DE','ev','kath') );
  $this->add_desc( $this->get_yday(26, 12), 'Stephanus', array('kath') );
  $this->add_desc( $this->get_yday(26, 12), '2. Weihnachtstag', array('DE','ev','kath') );
  $this->add_desc( $this->get_yday(27, 12), 'Johannes', array('kath') );
  $this->add_desc( $this->get_yday(28, 12), 'Unschuldige Kinder', array('kath') );

  $holyfamily_yday = $this->get_yday(30,12);
  if( 24+7-($xmas_wday+2) <= 31 ) {
    $holyfamily_yday = $xmas_yday+7-($xmas_wday+2);
  }
  $this->add_desc( $holyfamily_yday, 'Fest der Hl.Familie', array('kath'));

  $this->add_desc( $this->get_yday(31, 12), 'Silvester', array('de') );
}


/* Feiertags-Filter.
 * $scope: scope of organizations where day is valid (as array)
 * $return: filtered scope of organizations (as array) */
function scope_filter($scope) {
  //global $de;
  //global $state;
  //global $ev;
  //global $kath;

  $result = array();
  $states = array('BB','BE','BW','BY','HB','HH','HE','MV','NI','NW','RP','SL','SN','ST','SH','TH');

  for($i=0; $i<sizeof($scope); $i++) {
    if($this->de && strtoupper($scope[$i])=='DE') array_push( $result, $scope[$i] );
    if($this->state!=false && in_array( strtoupper($scope[$i]), $states )) array_push( $result, $scope[$i] );
    if($this->ev && strtoupper($scope[$i])=='EV') array_push( $result, $scope[$i] );
    if($this->kath && strtoupper($scope[$i])=='KATH') array_push( $result, $scope[$i] );
  }

  return $result;
}

/* Beschreibung zu einem Tag hinzufuegen.
 * $yday: day-of-year (0-based)
 * $title: title
 * $scope: scope of organizations where day is valid (as array) */
function add_desc($yday,$title,$scope) {
  //global $days;
  $scope = $this->scope_filter($scope);
  if( sizeof($scope) > 0 ) {
    if( !isset($this->days[$yday]) || !is_array($this->days[$yday]) ) $this->days[$yday] = array();
    array_push( $this->days[$yday], array($yday,$title,$scope) );
  }
}

/* Nummer eines Tages im Jahr ermitteln.
 * $day: day-of-month (1-based)
 * $month: month (1-based)
 * return: day-of-year (0-based) */
function get_yday($day,$month) {
  //global $year;
  $tmp = getdate(mktime(0,0,0,$month,$day,$this->year));
  return $tmp['yday'];
}

/* Beschreibung zu einem Tag abfragen.
 * $yday: day-of-year (0-based)
 * return: array of descriptions ($title,$scope) */
function get_desc($yday) {
  //global $days;
  $result = array();
  if(isset($this->days[$yday]) && is_array($this->days[$yday])) {
    for($i=0; $i<sizeof($this->days[$yday]); $i++) {
      array_push( $result, array($this->days[$yday][$i][1],$this->days[$yday][$i][2]) );
    }
  }
  return $result;
}

/* Feiertagsstatus abfragen (Deutschland).
 * $yday: day-of-year (0-based)
 * return: true if holiday, otherwise false */
function is_holiday($yday) {
  //global $state;
  $result = false;
  $tmp = $this->get_desc($yday);
  for($i=0; $i<sizeof($tmp); $i++) {
    for($j=0; $j<sizeof($tmp[$i][1]); $j++) {
      if($tmp[$i][1][$j]=='DE' || $tmp[$i][1][$j]==strtoupper($this->state)) {
        $result = true;
        break;
      }
    }
  }
  return $result;
}

/* Feiertagsstatus abfragen (Bundesland).
 * $scope: scope of organizations where day is valid (as array)
 * return: true if holiday, otherwise false */
function is_dependant_holiday($scope) {
  $result = false;
  for($j=0; $j<sizeof($scope); $j++) {
    if($scope[$j]=='DE') {
      $result = false;
      return $result;
    }
    if(strtoupper($scope[$j])==$scope[$j]) {
      $result = true;
    }
  }
  return $result;
}

/* Feiertagsstatus abfragen (Bundesland).
 * $scope: scope of organizations where day is valid (as array)
 * return: scope of organizations where day is holiday (as array)*/
function holiday_depends_on($scope) {
  $result = array();
  for($j=0; $j<sizeof($scope); $j++) {
    if($scope[$j]=='DE') {
      $result = array('DE');
      return $result;
    }
    if(strtoupper($scope[$j])==$scope[$j]) {
      array_push( $result, $scope[$j] );
    }
  }
  return $result;
}

/* Feiertagsstatus abfragen (Bundesland).
 * $scope: scope of organizations where day is valid (as array)
 * return: scope of organizations where day is holiday (as comma-separated string)*/
function holiday_depends_on_string($scope) {
  $result = '';
  $tmp = $this->holiday_depends_on($scope);
  for($i=0; $i<sizeof($tmp); $i++) {
    if($i!=0) $result .= ',';
    $result .= $tmp[$i];
  }
  return $result;
}

/* Kurzname fuer Tag abfragen.
 * $wday: day-of-week (0-based)
 * return: short name of weekday */
function get_wday_shortname($wday) {

  $wday_names = array('So','Mo','Di','Mi','Do','Fr','Sa');
  return $wday_names[$wday];
}

/* Kurzname fuer Tag abfragen.
 * $month: month (0-based)
 * return: name of month */
function get_month_name($month) {
  $month_names = array('Januar', 'Februar', 'März', 'April', 'Mai', 'Juni',
   'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember');
  return $month_names[$month-1];
}

/* PDF erzeugen (Din A4 Querformat). */
function draw_pdf_landscape() {
  //global $year;
  //global $pdf;
  //global $download;

  $this->pdf = new FPDF('L','mm','A4');
  $this->pdf->SetTitle('Kalender');
  $this->pdf->SetAuthor('Manuel Haim');
  $this->pdf->SetCreator('kalender.php');

  $this->pdf->AddPage();

  $this->pdf->SetFont('Arial','B',8);
  $linewidth=0.3;
  $this->pdf->SetLineWidth($linewidth);
  $this->pdf->SetDrawColor(0,0,0);

  $cell_width = 42;
  $cell_height = 5.25;
  $raster_width = 45;
  $raster_height = 5.25;
  $offset_x = 15;
  $offset_y = 22;

  $max_descs = 2;

  $this->pdf->SetFont('Arial','B',20);
  $this->pdf->Text($offset_x,$offset_y-$raster_height,$this->year);

  $this->pdf->SetFont('Arial','B',8);

  for($month=1; $month<=6; $month++) {
    $this->draw_pdf_month($month, $cell_width, $cell_height, $raster_width, $raster_height,
     $offset_x+($month-1)*$raster_width, $offset_y, $max_descs);
  }

  $this->pdf->AddPage();

  $this->pdf->SetFont('Arial','B',20);
  $this->pdf->Text($offset_x+5*$raster_width+$cell_width-$this->pdf->GetStringWidth($this->year),$offset_y-$raster_height,$this->year);

  for($month=7; $month<=12; $month++) {
    $this->draw_pdf_month($month, $cell_width, $cell_height, $raster_width, $raster_height,
     $offset_x+($month-7)*$raster_width, $offset_y, $max_descs);
  }

  if($this->download) {
    $this->pdf->Output('kalender.pdf','D');
  } else {
    $this->pdf->Output('kalender.pdf','I');
  }
}

/* PDF erzeugen (Din A4 Hochformat). */
function draw_pdf_portrait() {
  //global $year;
  //global $pdf;
  //global $download;

  $this->pdf = new FPDF('P','mm','A4');
  $this->pdf->SetTitle('Kalender');
  $this->pdf->SetAuthor('Manuel Haim');
  $this->pdf->SetCreator('kalender.php');

  $this->pdf->AddPage();

  $this->pdf->SetFont('Arial','B',8);
  $linewidth=0.3;
  $this->pdf->SetLineWidth($linewidth);
  $this->pdf->SetDrawColor(0,0,0);

  $cell_width = 29;
  $cell_height = 8.25;
  $raster_width = 32;
  $raster_height = 8.25;
  $offset_x = 10;
  $offset_y = 22;

  $max_descs = 3;

  $this->pdf->SetFont('Arial','B',20);
  $this->pdf->Text($offset_x,$offset_y-$raster_height,$this->year);

  $this->pdf->SetFont('Arial','B',8);

  for($month=1; $month<=6; $month++) {
    $this->draw_pdf_month($month, $cell_width, $cell_height, $raster_width, $raster_height,
     $offset_x+($month-1)*$raster_width, $offset_y, $max_descs);
  }

  $this->pdf->AddPage();

  $this->pdf->SetFont('Arial','B',20);
  $this->pdf->Text($offset_x+5*$raster_width+$cell_width-$this->pdf->GetStringWidth($this->year),$offset_y-$raster_height,$this->year);

  for($month=7; $month<=12; $month++) {
    $this->draw_pdf_month($month, $cell_width, $cell_height, $raster_width, $raster_height,
     $offset_x+($month-7)*$raster_width, $offset_y, $max_descs);
  }

  if($this->download) {
    $this->pdf->Output('kalender.pdf','D');
  } else {
    $this->pdf->Output('kalender.pdf','I');
  }
}


/* Zeichnet eine Monatsspalte.
 * $month: month (1-based)
 * $cell_width: width of a day cell
 * $cell_height: height of a day cell
 * $raster_width: horizontal distance between cell anchors
 * $raster_height: vertical distance between cell anchors
 * $offset_x: horizontal offset of first day cell
 * $offset_y: vertical offset of first day cell
 * $max_descs: maximum number of entries per day */
function draw_pdf_month($month, $cell_width, $cell_height, $raster_width, $raster_height, $offset_x, $offset_y,
 $max_descs) {
  //global $year;
  //global $pdf;

  $month_days = date('t',mktime(0,0,0,$month,1,$this->year));

  for($day=0; $day<32; $day++) {
    // Hintergrund
    if($day!=0 && $day<=$month_days) {
      $wday = date('w',mktime(0,0,0,$month,$day,$this->year));
      $background = false;
      if($wday==6) {
        // Samstag
        $this->pdf->SetDrawColor(230,230,230);
        $this->pdf->SetFillColor(230,230,230);
        $background = true;
      }
      if($this->is_holiday($this->get_yday($day,$month))) { //Feiertag
        $this->pdf->SetDrawColor(255,128,128);
        $this->pdf->SetFillColor(255,128,128);
        $background = true;
      }
      if($wday==0) {
        // Sonntag
        $this->pdf->SetDrawColor(179,179,179);
        $this->pdf->SetFillColor(179,179,179);
        $background = true;
      }
      if($background) {
        $this->pdf->Rect($offset_x, $offset_y+($day-1)*$raster_height, $cell_width, $cell_height, 'DF');
        $this->pdf->SetDrawColor(0,0,0);
      }
    }
  }

  $asterisks = array();

  for($day=0; $day<32; $day++) {
    // Linien
    $this->pdf->SetDrawColor(0,0,0);
    $this->pdf->Line($offset_x, $offset_y+$day*$raster_height, $offset_x+$cell_width, $offset_y+$day*$raster_height);

    // Monatsname
    if($day==0) {
      $this->pdf->SetFont('Arial','B',11);
      $monthname = $this->get_month_name($month);
      $monthname = iconv('UTF-8', 'windows-1252', $monthname);
      $this->pdf->Text($offset_x+($cell_width-$this->pdf->GetStringWidth($monthname))/2, $offset_y-0.5,$monthname);
    }

    // Monatstage
    if($day!=0 && $day<=$month_days) {
      $wday = date('w',mktime(0,0,0,$month,$day,$this->year));
      if($wday==6 || $wday==0) {
        // Samstag oder Sonntag
        $this->pdf->SetTextColor(255,0,0);
      }

      // Nummer
      $this->pdf->SetFont('Arial','B',8);
      $this->pdf->Text($offset_x, $offset_y+$day*$raster_height-0.5, $day.'.');
      $number_width = $this->pdf->GetStringWidth('00.');

      // Tag
      $this->pdf->SetFont('Arial','B',6);
      $this->pdf->Text($offset_x+$number_width, $offset_y+$day*$raster_height-0.5, $this->get_wday_shortname($wday));
      $wday_width = $this->pdf->GetStringWidth('Mm ');

      $this->pdf->SetTextColor(0,0,0);

      // Beschreibung
      $this->pdf->SetFont('Arial','',6);
      $desc = $this->get_desc($this->get_yday($day,$month));
      for($i=0; $i<min(sizeof($desc),$max_descs); $i++) {
        $desc_title = $desc[$i][0];
        $desc_title = iconv('UTF-8', 'windows-1252', $desc_title);
        $depends = '';
        if($this->is_dependant_holiday($desc[$i][1])) {
          array_push( $asterisks, $this->holiday_depends_on_string($desc[$i][1]) );
          $depends = str_repeat('*', sizeof($asterisks));
        }
        $this->pdf->Text($offset_x+$number_width+$wday_width,
         $offset_y+$day*$raster_height-0.5+2.5*($i+1-min(sizeof($desc),$max_descs)),
         $desc_title.$depends);
      }

    }

  }

  // Sternchen
  $this->pdf->SetFont('Arial','',6);
  for($i=0; $i<sizeof($asterisks); $i++) {
    $this->pdf->Text($offset_x, $offset_y+31*$raster_height+2.5*(1+$i), str_repeat('*',$i+1).$asterisks[$i]);
  }

}

/* HTML erzeugen. */
function draw_html() {
  //global $year;

  echo '<h1>' . $this->year . '</h1>';

  for($month=1; $month<=12; $month++) {
    $this->draw_html_month($month);
  }

}

function draw_html_month($month) {
  //global $year;

  $month_days = date('t',mktime(0,0,0,$month,1,$this->year));

  $asterisks = array();

  for($day=0; $day<32; $day++) {
    // Hintergrund
    if($day!=0 && $day<=$month_days) {
      $wday = date('w',mktime(0,0,0,$month,$day,$this->year));
      $background = '#ffffff';
      if($wday==6) {
        // Samstag
        $background = '#e6e6e6';
      }
      if($this->is_holiday($this->get_yday($day,$month))) { //Feiertag
        $background = '#ff8080';
      }
      if($wday==0) {
        // Sonntag
        $background = '#ff9999'; // '#b3b3b3';
      }
    }

    // Monatsname
    if($day==0) {
      echo '<h3>' . $this->get_month_name($month) . ' ' . $this->year . '</h3>';
    }

    // Monatstage
    if($day!=0 && $day<=$month_days) {
      $textcolor = '#000000';
      $wday = date('w',mktime(0,0,0,$month,$day,$this->year));
      if($wday==6 || $wday==0) {
        // Samstag oder Sonntag
        $textcolor = '#bd181d';
      }

      // Nummer
      echo '<span style="display:block;width:200px;color:' . $textcolor .
       ';background-color:' . $background . '">' . $day . '.&nbsp;';

      // Tag
      echo $this->get_wday_shortname($wday);

      //echo '</span>';

      // Beschreibung
      $desc = $this->get_desc($this->get_yday($day,$month));
      for($i=0; $i<sizeof($desc); $i++) {
        $depends = '';
        if($this->is_dependant_holiday($desc[$i][1])) {
          array_push( $asterisks, $this->holiday_depends_on_string($desc[$i][1]) );
          $depends = str_repeat('*', sizeof($asterisks));
        }
        //if($i>0) {
          echo '<br>';
        //}
        echo '<em>' . $desc[$i][0].$depends . '</em>';
      }

      echo '</span>';

      echo '<br>';

    }

  }

  // Sternchen
  for($i=0; $i<sizeof($asterisks); $i++) {
    echo str_repeat('*',$i+1).$asterisks[$i] . '<br>';
  }
}


function getscript() {
  header('Content-type: application/octet-stream');
  header('Content-Disposition: attachment; filename="'
   .basename($_SERVER['SCRIPT_FILENAME']).'"');
  readfile($_SERVER['SCRIPT_FILENAME']);
}


} // End of class Kalender.
?>
