 {w tag {overTag {}}} {
    if {[string length $overTag] == 0} {
	$w tag raise $tag
    } elseif [regexp "${tag}.*${overTag}" [$w tag names]] {
	$w tag raise $tag $overTag
    }
}
proc MimeInsertSeparator {tkw part width} {
    global mimeHdr mime

    if [$tkw compare insert != "insert linestart"] {
       $tkw insert insert "\n"
    }
    if {$mime(showSeparator)} {
	set looks {-relief sunken \
	  -borderwidth 2 \
	  -font -*-*-*-*-*-*-$width-*-*-*-*-*-iso8859-* \
	  -background $mimeHdr($part,color)}
	set sepLabel [MimeLabel $width separator]
	MimeWithTagging $tkw $sepLabel [MimeLabel $part part] $looks {
	    $tkw insert insert \n
	}
    } else {
	$tkw insert insert \n
    }
}
proc MimeClearHigherTags {w tag start end} {
    set tagList [$w tag names]
    regexp -indices "${tag}(.*)" $tagList match tagsOver
    set tagsOver [eval {string range $tagList} $tagsOver]
    foreach tag $tagsOver {
	$w tag remove $tag $start $end
    }
}
proc Mime_GetFont {w weight slant fontSet size charset} {
    global mime
    # weight = {bold medium}
    # slant = {i r}
    # fontSet = {plain title fixed proportional}
    # size = pts*10
    # charset = any valid mime charset

    if {[string match medium-r-plain-$mime(fontSize)-us-ascii \
	    $weight-$slant-$fontSet-$size-$charset] || \
	    [string match medium-r-plain-$mime(fontSize)-iso-8859-1 \
	    $weight-$slant-$fontSet-$size-$charset]} {
	# Special case the most common situation
	if ![info exists mime(defaultFont)] {
	    set mime(defaultFont) [option get $w font Font]
	    if {[string length $mime(defaultFont)] == 0} {
		set mime(defaultFont) fixed
	    }
	}
	return $mime(defaultFont)
    }
    if [regexp {^fixed$|^plain$} $fontSet] {
	set spacing "*"
	# someone tell me the difference between "m" and "c"
    } else {
#	set spacing "p"
	set spacing "*"
    }
    if {[info exists mime(registry,$charset)] &&
	($mime(registry,$charset) != {})} {
	set registry $mime(registry,$charset)
    } else {
	set registry "iso8859"
    }
    if {[info exists mime(encoding,$charset)] &&
	($mime(encoding,$charset) != {})} {
	set encoding $mime(encoding,$charset)
    } else {
	set encoding "*"
    }

    # Let's try and find a working font
    set i 1
    set family $mime(family,$charset,$fontSet,$i)
    set size [string trim $size]

    set font "-*-$family-$weight-$slant-*-*-*-$size-*-*-$spacing-*-$registry-$encoding"
    $w tag add dummyTag end
    while {[catch {$w tag configure dummyTag -font $font} err]} {
	# That one wasn't any good; let's look for another one
	incr i

	if [catch {set family $mime(family,$charset,$fontSet,$i)}] {
	    # No entry?	 Oh well, at least this will be the right size
	    # and will have the right encoding.  If it has a problem,
	    # we want to let the problem be handled outside this
	    # routine.
	    return "-*-*-*-*-*-*-*-$size-*-*-*-*-$registry-$encoding"
	} else {
	    set font "-*-$family-$weight-$slant-*-*-*-$size-*-*-$spacing-*-$registry-$encoding"
	}
    }
    return $font
}

proc MimeGetRule {part method atribVar \
		  {f_multipart_filenames {}} {m_multipart_filenames {}}} {
    upvar $atribVar atrib
    global mimeHdr

    foreach key $mimeHdr($part,params) {
	set contentParams($key) $mimeHdr($part,param,$key)
    }
    mailcap_getrule $mimeHdr($part,type) contentParams $method \
	atrib [Mime_GetUnencodedFile $part] $f_multipart_filenames \
	$m_multipart_filenames
}

proc MimeGetOrigFile {part} {
    global mimeHdr

    if ![info exists mimeHdr($part,origFile)] {
	Mime_GetUnencodedFile $part
    }
    return $mimeHdr($part,origFile)
}
proc MimeCheckRule {part method} {
    global mimeHdr

    if ![info exists mimeHdr($part,type)] {
	return 0
    }
    mailcap_checkrule $mimeHdr($part,type) contentParams $method
}
proc MimeMailcapView { part subparts } {
    global mimeHdr
    if [catch {MimeGetRule $part "" atrib $subparts} rule] {
	Exmh_Status $rule
	return
    }
    Exmh_Status $rule
    if [catch {
	if [info exists atrib(needsterminal)] {
	    exec xterm -e sh -c $rule &
	} else {
	    exec sh -c $rule &
	}
    } err] {
	Exmh_Status $err warn
    }
}
proc MimeMailcapPrint { part subparts } {
    global mimeHdr
    if [catch {MimeGetRule $part print atrib $subparts} rule] {
	Exmh_Status $rule
	return
    } else {
	Exmh_Status Printing...
	if [catch {exec sh -c $rule} err] {
	    Exmh_Status $err warn
	}
    }
}
proc Mime_ShowAudio { tkw part } {
    global mimeHdr
    TextButton $tkw "Play attached audio" [list MimeShowAudioNow $tkw $part]
    $tkw insert insert \n\n
    TextButton $tkw "Save audio file" [list Mime_SavePiece $part $mimeHdr($part,type)]
    $tkw insert insert \n
}
proc MimeShowAudioNow { tkw part } {
    global mimeHdr mime
    Mime_GetUnencodedFile $part
    if [catch {MimeGetRule $part "" atrib} audioCommand] {
	Exmh_Status $audioCommand
    } else { 
	Exmh_Status $audioCommand
	exec sh -c $audioCommand > /dev/null &
    }
}

proc Mime_Uudecode { infile outfile } {
    set tmpfile [Env_Tmp]/exmh.uud.[file tail $infile].[pid]
    if [catch {open $tmpfile w 0600} out] {
	Exmh_Status $out
    } else {
	if [catch {open $infile} in] {
	    Exmh_Status $in
	    close $out
	} else {
	    set print 0
	    while {[gets $in line] >= 0} {
		if [regexp {begin ([0-9]+) } $line x perm] {
		    puts $out "begin $perm $outfile"
		    set print 1
		} elseif {$print} {
		    puts $out $line
		}
	    }
	    close $out
	    close $in
	    Exmh_Status "uudecode [file tail $infile] > $outfile"
	    if [catch {exec uudecode < $tmpfile} err] {
		Exmh_Status $err error
	    }
	}
	File_Delete $tmpfile
    }
}

proc Mime_EudoraFilename {name} {
    set i [string last "/" $name]
    if {$i > -1} {
	set name [string range $name [expr $i + 1] end]
    }
    regsub -all {[^A-Za-z0-9_!#$&().~{}-]} $name "_" name
    set name [string toupper $name]
    set bits [split $name .]
    if {[llength $bits] == 1} {
	return [format "%.8s" $name]
    }
    set firstbit [lindex $bits 0]
    set bits [lrange $bits 1 end]
    while {[string length $firstbit] < 8 && [llength $bits] > 1} {
	append firstbit "_"
	append firstbit [lindex $bits 0]
	set bits [lrange $bits 1 end]
    }
    set lastbit [lindex $bits end]
    return [format "%.8s.%.3s" $firstbit $lastbit]
}

proc Mime_MakeBoundary { end } {

    # Old boundary was made by
    # regsub -all "\[ \x7f-\xff\]" [exec date] _ date
    # This way works at least with GNU date.

    regsub -all {[^0-9]|[0-9][0-9][0-9][0-9]} [exec date] {} boundary
    regsub {^0*} $boundary {} boundary	;# No octal interpretation, please
    set boundary [expr $boundary*[pid]]
    return "==_Exmh_$boundary$end"
}
proc Mime_Magic { fileName } {
    global exmh env
    Exmh_Debug Mime_Magic $fileName

    foreach m { "-m $exmh(userLibrary)/.magic" \
     "-m $exmh(library)/local.magic" ""} {
	if [catch {eval exec file $m $fileName} result] {
	    continue
	}

	set result [string trim [lindex [split $result :] 1]] 

	foreach res { magic_u magic_l magic_ } {
	    set contentType [option get . $res$result {}]
	    if [string length $contentType] {
		return $contentType
	    }
	}
    }

    return
}
proc Mime_ShowXApp { tkw part } {
    global mimeHdr
    Exmh_Debug Mime_ShowXApp $part

    set descr [Mime_TypeDescr $part]
    if [MimeCheckRule $part ""] {
	$tkw insert insert \n
	TextButton $tkw "Open ${descr}..." [list MimeMailcapView $part ""]
    }
    if [MimeCheckRule $part "print"] {
	$tkw insert insert "  "
	TextButton $tkw "Print" [list MimeMailcapPrint $part ""]
    }
    $tkw insert insert "  "
    TextButton $tkw "Save..." \
     [list Mime_SavePiece $part $mimeHdr($part,type)]
    $tkw insert insert \n
}
