comment {
    Bereiche mit Tabulatoren werden zum TeX-Makro \halign{...} umgesetzt.
    Tabulator-Bereiche werden so behandelt:
    (1) Die Zeilen werden eingesammelt und auf gleiche Tab-Zahl gebracht.
    (2) Die Felder werden in Spalten einsortiert.
    (3) Die Spalten werden auf Fließkomma- oder Ganzzahl untersucht.
    (4) Reine Fließkommaspalten werden durch
    Vorkomma- und Nachkommaspalten ersetzt.
    (5) Fließkomma- und Ganzzahlspalten werden rechtsbündig ausgerichtet.
}

proc getTabulatorIndices {txt} {
    set tabPat {(?:(?:[^\n]*\t)+[^\n]*\n)+}
    regexp -inline -all -indices $tabPat $txt
}

proc getTextTabSequence {txt} {
    set indexPairs [getTabulatorIndices $txt]
    set tabParts {}
    foreach {indexPair} $indexPairs {
	let {from to} $indexPair
	lappend tabParts [string range $txt $from $to]
    }
    set textIndices {}
    lappend textIndices -1
    foreach indexPair $indexPairs {
	let {from to} $indexPair
	lappend textIndices [expr {$from-1}] [expr {$to+1}]
    }
    lappend textIndices [string length $txt]
    set textParts {}
    foreach {from to} $textIndices {
	lappend textParts [string range $txt $from $to]
    }
    set result {}
    foreach textPart $textParts tabPart $tabParts {
	lappend result $textPart $tabPart
    }
    lrange $result 0 end-1
}

proc txt2tabRows {tabPart} {
    set lines [split [string trim $tabPart] \n]
    set colNum 0
    foreach line $lines {
	set length [llength [split $line \t]]
	if {$length > $colNum} {
	    set colNum $length
	}
    }
    set rowNum [llength $lines]
    set rows {}
    foreach i [range $rowNum] {
	set row [split [lindex $lines $i] \t]
	while {[llength $row] < $colNum} {
	    lappend row {}
	}
	lappend rows $row
    }
    set rows
}

proc txt2tabCols {tabPart} {
    set rows [txt2tabRows $tabPart]
    set rowNum [llength $rows]
    set colNum [llength [lindex $rows 0]]
    set cols {}
    foreach i [range $colNum] {
	set col {}
	foreach j [range $rowNum] {
	    lappend col [llindex $rows $j $i]
	}
	lappend cols $col
    }
    set cols
}

proc colType {col} {
    if {[globalSetting numberAlign] eq "left"} {
	return string
    }
    # try on integer
    set isInteger 1
    foreach f $col {
	if {![regexp {^[0-9+-]*$} $f]} {
	    set isInteger 0
	    break
	}
    }
    if {$isInteger} {
	return integer
    }
    let {Punkt Komma} [globalSetting 1000.dezimal,]
    set pat [subst -nocommand {^[+-]?[0-9$Punkt]+($Komma[0-9]+)?$}]
    foreach f $col {
	if {![regexp $pat $f]} {
	    return string
	}
    }
    return float
}

proc splitFloatCol {col} {
    let {Punkt Komma} [globalSetting 1000.dezimal,]
    let vorkommas {} nachkommas {}
    foreach float $col {
	let {vorkomma nachkomma} [split $float $Komma]
	lappend vorkommas $vorkomma
	lappend nachkommas $nachkomma
    }
    list $vorkommas $nachkommas
}

proc txt2tabColStruct {tabPart} {
    set cols [txt2tabCols $tabPart]
    set cols1 {}
    set types1 {}
    foreach col $cols type [map colType $cols] {
	switch $type {
	    float {
		lappend types1 vorkomma nachkomma
		let {vorkommas nachkommas} [splitFloatCol $col]
		lappend cols1 [map [lambda {numString} {
		    # string map "- \u2013" $numString
		    string map {- $-$ + $+$} $numString
		}] $vorkommas] [map [lambda {x} {
		    let {Punkt Komma} [globalSetting 1000.dezimal,]
		    if {$x ne ""} {
			return "$Komma$x"
		    }
		}] $nachkommas]
	    }
	    integer {
		lappend types1 $type
		lappend cols1 [map [lambda {numString} {
		    string map "- \u2013" $numString
		}] $col]
	    }
	    default {
		lappend types1 $type
		lappend cols1 $col
	    }
	}
    }
    list $types1 $cols1
}

proc txt2tabLineStruct {tabPart} {
    let {types cols} [txt2tabColStruct $tabPart]
    set colNum [llength $cols]
    set rowNum [llength [lindex $cols 0]]
    set result {}
    lappend result $types
    foreach i [range $rowNum] {
	set row {}
	foreach j [range $colNum] {
	    lappend row [llindex $cols $j $i]
	}
	lappend result $row
    }
    set result
}

proc tabRange2tex {tabPart} {
    set struct [txt2tabLineStruct $tabPart]
    set types [lindex $struct 0]
    set lines [lrange $struct 1 end]
    set patterns [map [lambda {type} {
	switch $type {
	    vorkomma {
		return " \\hfill \#"
	    }
	    nachkomma {
		return "\# \\hfill "
	    }
	    integer {
		return " \\hfill \# "
	    }
	    default {
		return " \# \\hfill "
	    }
	}
    }] $types]
    set texLines {}
    lappend texLines [join $patterns &]
    foreach line $lines {
	lappend texLines [join [map unicode2tex $line ] {&}]
    }
    set result \\halign
    append result \{ \n\
	[join $texLines \\cr\n]\
	\\cr \n \}
}

proc plaintext2tex {txt} {
    set sequence [getTextTabSequence $txt]
    set plaintext [lindex $sequence 0]
    set result [unicode2texWithItems [hyphenated $plaintext]]
    foreach {tabulatortext plaintext} [lrange $sequence 1 end] {
	append result\
	    \n\n\
	    [tabRange2tex $tabulatortext]\
	    \n\n\
	    [unicode2texWithItems [hyphenated [string trim $plaintext]]]
    }
    string trim $result
}