#Region - TimeStamp
; 2013-11-15 12:39:53
#EndRegion - TimeStamp

#include <Date.au3>

; Anzahl Zeichen in jeder Zeile, Minimum ist 20 - ein Monat.
Global $iPrintSize = 80

; Anzahl Monate, die nebeneinander gedruckt werden sollen. Mit "0" wird das automatisch errechnet.
; Die Zahl wird korrigiert, wenn damit kein rechteckiger Ausdruck möglich ist.
; Wenn der Druckbereich zu schmal ist für die gegebene Anzahl Monate, wird diese automatisch errechnet.
Global $iSideBySide = 3

; Anzahl Leerzeichen zwischen den Monaten.
Global $iSpace = 4

; Titel festlegen
Global $sTitle = '[ MEIN KALENDER ]'

; Ausgabe in Konsole und/oder Terminalsimulation (GUI)
Global Const $_CONSOLE  = 1
Global Const $_TERMINAL = 2
Global Const $_BOTH     = BitOR($_CONSOLE, $_TERMINAL)

; Array mit Zellen-Labeln für Terminalsimulation
Global $aRawCol[1][2]


_CreateCalendar( 2013, $_BOTH )


Func _CreateCalendar($_iYear, $_iOutput)
	Local $aMon[12] = ['       Januar       ', '      Februar       ', '        März        ', _
	                   '        April       ', '        Mai         ', '        Juni        ', _
	                   '        Juli        ', '       August       ', '      September     ', _
	                   '       Oktober      ', '      November      ', '      Dezember      ']
	Local $sHead = 'Mo Di Mi Do Fr Sa So'
	Local $aDaysInMonth[12] = [31,28,31,30,31,30,31,31,30,31,30,31]
	If _DateIsLeapYear($_iYear) Then $aDaysInMonth[1] = 29

	; == Datum mit in Wochentagstabelle für das gesamte Jahr verknüpfen
	Local $aAllDaysInMonth[6][7][12]   ; [ Zeilen ][ Wochentage ][ Monate ]
	Local $iDay = 1, $iShift
	For $i = 1 To 12
		$iShift = _DateToDayOfWeekISO($_iYear, $i, 1) -1
		For $j = 0 To 5
			For $k = $iShift To 6
				$aAllDaysInMonth[$j][$k][$i-1] = $iDay
				$iDay += 1
				If $iDay > $aDaysInMonth[$i-1] Then ExitLoop(2)
			Next
			$iShift = 0
		Next
		$iDay = 1
	Next

	; == Prüfe Anzahl Monate nebeneinander, berechnen wenn erforderlich
	If $iSideBySide > 0 Then
		If $iPrintSize < ($iSideBySide *(20 +$iSpace) -$iSpace) Then $iSideBySide = 0
	EndIf
	Switch $iSideBySide
		Case 0
			$iSideBySide = Int($iPrintSize /(20 +$iSpace))
			If $iPrintSize < 20 Then Return _PrintLine($_iOutput, 'Escape: Size Error')
			If $iPrintSize < (20 +$iSpace) Then $iSideBySide = 1
		Case 5
			$iSideBySide = 4
		Case 7 To 11
			$iSideBySide = 6
	EndSwitch

	; == Ausgabe auch in simuliertes Terminal
	If BitAND($_iOutput, $_TERMINAL) Then
		Local $iLines = 12 /$iSideBySide *8 + 6
		ReDim $aRawCol[$iLines][$iPrintSize]
		GUICreate('Simulated Printer', $iPrintSize*8, $iLines*16)   ; Größe jeder Zelle: 8 px * 16 px
		GUISetBkColor(0x00008E)
		GUISetFont(9, 400, Default, 'Courier New')

		For $i = 0 To $iLines -1
			For $j = 0 To $iPrintSize -1
				$aRawCol[$i][$j] = GUICtrlCreateLabel('', $j*8, $i*16, 8, 16, 2) ; $ES_RIGHT = 2
				GUICtrlSetColor(-1, 0xFFFF22)
			Next
		Next

		GUISetState()
	EndIf

	; == Leerzeichenstring erstellen
	Local $sSpace = ''
	For $i = 1 To $iSpace
		$sSpace &= ' '
	Next

	; == Header drucken
	_PrintLine($_iOutput, @LF)
	_PrintLine($_iOutput, $sTitle, @LF)
	_PrintLine($_iOutput, StringRegExpReplace($_iYear, '(\d)(\d)(\d)(\d)', '$1 $2 $3 $4'), @LF)

	; == Daten für jede Zeile zusammenstellen/drucken in Abhängigkeit zur Anzahl Monate nebeneinander
	Local $sLine, $iRight, $sTmp1, $sTmp2
	For $n = 0 To 12 /$iSideBySide -1
		$sTmp1 = ''
		$sTmp2 = ''
		For $z = 0 To $iSideBySide -1
			$sTmp1 &= $aMon[$iSideBySide *$n+$z] & $sSpace
			$sTmp2 &= $sHead & $sSpace
		Next
		_PrintLine($_iOutput, StringTrimRight($sTmp1, $iSpace))
		_PrintLine($_iOutput, StringTrimRight($sTmp2, $iSpace))
		For $j = 0 To 5
			$sLine = ''
			For $i = 1 To $iSideBySide
				For $k = 0 To 6
					$iRight = 3
					If $k = 0 Then $iRight = 2
					$sLine &= StringRight('   ' & $aAllDaysInMonth[$j][$k][$iSideBySide*$n+$i-1], $iRight)
				Next
				If $i < $iSideBySide Then $sLine &= $sSpace
			Next
			_PrintLine($_iOutput, $sLine)
		Next
	Next

	If BitAND($_iOutput, $_TERMINAL) Then
		Do
		Until GUIGetMsg() = -3
	EndIf
EndFunc  ;==>_CreateCalendar

Func _PrintLine($_iOutput, $_sLine, $_sLF='')
	Local Static $iLine = 0
	If BitAND($_iOutput, $_CONSOLE) Then
		Local $iLen = StringLen($_sLine)
		Local $sSpace = '', $sLeft = ''
		For $i = 1 To $iPrintSize-1
			$sSpace &= ' '
		Next
		If $iLen < $iPrintSize Then $sLeft = StringLeft($sSpace, Int(($iPrintSize-$iLen)/2))
		ConsoleWrite($sLeft & $_sLine & $_sLF & @LF)
	EndIf
	If BitAND($_iOutput, $_TERMINAL) Then
		Local $aLine = StringSplit($_sLine, ''), $iIndexStart = 0
		If $aLine[0] < $iPrintSize Then $iIndexStart = Int(($iPrintSize-$aLine[0])/2)
		For $i = 1 To $aLine[0]
			GUICtrlSetData($aRawCol[$iLine][$i+$iIndexStart], $aLine[$i])
		Next
	EndIf
	$iLine += 1
	If $_sLF <> '' Then $iLine += 1
EndFunc  ;==>_PrintLine

