# -*- tcl -*-
#
# fmt.text -- Engine to convert a doctools document into plain text.
#
# Copyright (c) 2003 Andreas Kupries <andreas_kupries@sourceforge.net>
#
################################################################
################################################################

# Load shared code and modify it to our needs.

dt_source _common.tcl
dt_source _text.tcl
proc c_copyrightsymbol {} {return "(c)"}

rename fmt_initialize     BaseInitialize
proc   fmt_initialize {} {BaseInitialize ; TextInitialize ; return}

################################################################
# Special manpage environments

proc NewExample {} {
    global currentEnv
    return [NewEnv Example {
	set    currentEnv(verbatim) 1
	append currentEnv(prefix)   "| "
	set    currentEnv(example) .
    }] ; # {}
}

proc Example {} {
    global currentEnv
    if {![info exists currentEnv(exenv)]} {
	SaveContext
	set verb [NewExample]
	RestoreContext

	# Remember verbatim mode in the base environment
	set currentEnv(exenv) $verb
	SaveEnv
    }
    return $currentEnv(exenv)
}

proc NewList {what} {
    # List environments
    # Per list several environments are required.

    switch -exact -- $what {
	enumerated {NewOrderedList}
	itemized   {NewUnorderedList}
	arguments -
	commands  -
	options   -
	tkoptions -
	definitions {NewDefinitionList}
    }
}

proc NewUnorderedList {} {
    global currentEnv lmarginIncrement

    # Itemized list - unordered list - bullet
    # 1. Base environment provides indentation.
    # 2. First paragraph in a list item.
    # 3. All other paragraphs.

    set base [NewEnv Itemized {
	incr currentEnv(lmargin)   $lmarginIncrement

	set bullet [Bullet currentEnv(bulleting)]
    }] ; # {}
    set first [NewEnv First {
	set currentEnv(wspfx) [::textutil::repeat::blank $lmarginIncrement]
	set currentEnv(listtype)  bullet
	set currentEnv(bullet) $bullet
    }] ; SetContext $base ; # {}

    set next [NewEnv Next {
	incr currentEnv(lmargin)   $lmarginIncrement
    }] ; SetContext $base ; # {}

    set currentEnv(_first) $first
    set currentEnv(_next)  $next
    set currentEnv(pcount) 0
    SaveEnv
    return
}

proc NewOrderedList {} {
    global currentEnv lmarginIncrement

    # Ordered list - enumeration - enum
    # 1. Base environment provides indentation.
    # 2. First paragraph in a list item.
    # 3. All other paragraphs.

    set base [NewEnv Enumerated {
	incr currentEnv(lmargin)   $lmarginIncrement

	set bullet [EnumBullet currentEnv(enumeration)]
    }] ; # {}
    set first [NewEnv First {
	set currentEnv(wspfx)  [::textutil::repeat::blank $lmarginIncrement]
	set currentEnv(listtype)  enum
	set currentEnv(bullet) $bullet
    }] ; SetContext $base ; # {}

    set next [NewEnv Next {
	incr currentEnv(lmargin)   $lmarginIncrement
    }] ; SetContext $base ; # {}

    set currentEnv(_first) $first
    set currentEnv(_next)  $next
    set currentEnv(pcount) 0
    SaveEnv
    return
}

proc NewDefinitionList {} {
    global currentEnv lmarginIncrement

    # Definition list - terms & definitions
    # 1. Base environment provides indentation.
    # 2. Term environment
    # 3. Definition environment

    set base [NewEnv DefL {
	incr currentEnv(lmargin)   $lmarginIncrement
    }] ; # {}
    set term [NewEnv Term {
	set currentEnv(verbatim) 1
    }] ; SetContext $base ; # {}

    set def [NewEnv Def {
	incr currentEnv(lmargin) $lmarginIncrement
    }] ; SetContext $base ; # {}

    set currentEnv(_term)       $term
    set currentEnv(_definition) $def
    SaveEnv
    return
}

################################################################
# Final layouting.

c_holdBuffers require

proc fmt_postprocess {text} {text_postprocess $text}


################################################################
# Implementations of the formatting commands.

c_pass 1 fmt_plain_text {text} NOP
c_pass 2 fmt_plain_text {text} {text_plain_text $text}

c_pass 1 fmt_manpage_begin {title section version} NOP
c_pass 2 fmt_manpage_begin {title section version} {
    Off
    set module      [dt_module]
    set shortdesc   [c_get_module]
    set description [c_get_title]
    set copyright   [c_get_copyright]

    set     hdr [list]
    lappend hdr "$title - $shortdesc"
    lappend hdr [c_provenance]
    lappend hdr "[string trimleft $title :]($section) $version $module \"$shortdesc\""
    set     hdr [join $hdr \n]

    Text $hdr
    CloseParagraph [Verbatim]
    Section NAME
    Text "$title - $description"
    CloseParagraph
    return
}

c_pass 1 fmt_moddesc   {desc} {c_set_module $desc}
c_pass 2 fmt_moddesc   {desc} NOP

c_pass 1 fmt_titledesc {desc} {c_set_title $desc}
c_pass 2 fmt_titledesc {desc} NOP

c_pass 1 fmt_copyright {desc} {c_set_copyright $desc}
c_pass 2 fmt_copyright {desc} NOP

c_pass 1 fmt_manpage_end {} NOP
c_pass 2 fmt_manpage_end {} {
    set sa [c_xref_seealso]
    set kw [c_xref_keywords]
    set ct [c_get_copyright]

    CloseParagraph
    if {[llength $sa] > 0} {Section {SEE ALSO} ; Text [join [lsort $sa] ", "] ; CloseParagraph}
    if {[llength $kw] > 0} {Section KEYWORDS   ; Text [join [lsort $kw] ", "] ; CloseParagraph}
    if {$ct != {}}         {Section COPYRIGHT  ; Text $ct ; CloseParagraph [Verbatim]}
    return
}

c_pass 1 fmt_section     {name {id {}}} NOP
c_pass 2 fmt_section     {name {id {}}} {CloseParagraph ; Section $name ; return}

c_pass 1 fmt_subsection  {name {id {}}} NOP
c_pass 2 fmt_subsection  {name {id {}}} {CloseParagraph ; Subsection $name ; return}

c_pass 1 fmt_para {} NOP
c_pass 2 fmt_para {} {CloseParagraph ; return}

c_pass 2 fmt_require {pkg {version {}}} NOP
c_pass 1 fmt_require {pkg {version {}}} {
    set result "package require $pkg"
    if {$version != {}} {append result " $version"}
    c_hold require $result
    return
}

c_pass 1 fmt_usage {cmd args} {c_hold synopsis "$cmd [join $args " "]"}
c_pass 2 fmt_usage {cmd args} NOP

c_pass 1 fmt_call  {cmd args} {c_hold synopsis "$cmd [join $args " "]"}
c_pass 2 fmt_call  {cmd args} {fmt_lst_item "$cmd [join $args " "]"}


c_pass 1 fmt_description {id} NOP
c_pass 2 fmt_description {id} {
    On
    set syn [c_held synopsis]
    set req [c_held require]

    if {$syn != {} || $req != {}} {
	Section SYNOPSIS
	if {($req != {}) && ($syn != {})} {
	    Text $req\n\n$syn
	} else {
	    if {$req != {}} {Text $req}
	    if {$syn != {}} {Text $syn}
	}
	CloseParagraph [Verbatim]
    }

    Section DESCRIPTION
    return
}

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

c_pass 1 fmt_list_begin {what {hint {}}} NOP
c_pass 2 fmt_list_begin {what {hint {}}} {
    #puts_stderr "<<fmt_list_begin $what>>"

    global currentEnv
    if {[info exists currentEnv(_definition)]} {
	CloseParagraph $currentEnv(_definition)
    } elseif {[info exists currentEnv(pcount)]} {
	if {$currentEnv(pcount) == 0} {CloseParagraph $currentEnv(_first)}
	if {$currentEnv(pcount) >  0} {CloseParagraph $currentEnv(_next)}
	incr currentEnv(pcount)
    } else {
	CloseParagraph
    }
    SaveContext
    NewList $what
    Off

    #puts_stderr "<<fmt_list_begin _____>>"
    return
}

c_pass 1 fmt_list_end {} NOP
c_pass 2 fmt_list_end {} {
    #puts_stderr "<<fmt_list_end>>"

    global currentEnv
    if {[info exists currentEnv(_definition)]} {
	CloseParagraph $currentEnv(_definition)
    } else {
	if {$currentEnv(pcount) == 0} {CloseParagraph $currentEnv(_first)}
	if {$currentEnv(pcount) >  0} {CloseParagraph $currentEnv(_next)}
    }
    RestoreContext

    #puts_stderr "<<fmt_list_end ____>>"
    return
}

c_pass 1 fmt_lst_item {text} NOP
c_pass 2 fmt_lst_item {text} {
    global currentEnv

    #puts_stderr "<<fmt_lst_item \{$text\}>>"

    if {[IsOff]} {
	On
    } else {
	CloseParagraph $currentEnv(_definition)
    }
    Text $text
    CloseParagraph $currentEnv(_term)

    #puts_stderr "<<fmt_lst_item _____>>"
    return
}

c_pass 1 fmt_bullet {} NOP
c_pass 2 fmt_bullet {} {
    global currentEnv
    if {[IsOff]} {On ; return}
    if {$currentEnv(pcount) == 0} {CloseParagraph $currentEnv(_first)}
    if {$currentEnv(pcount) >  0} {CloseParagraph $currentEnv(_next)}
    set  currentEnv(pcount) 0
    return
}

c_pass 1 fmt_enum {} NOP
c_pass 2 fmt_enum {} {
    global currentEnv
    if {[IsOff]} {On ; return}
    if {$currentEnv(pcount) == 0} {CloseParagraph $currentEnv(_first)}
    if {$currentEnv(pcount) >  0} {CloseParagraph $currentEnv(_next)}
    set  currentEnv(pcount) 0
    return
}

c_pass 1 fmt_cmd_def  {command} NOP
c_pass 2 fmt_cmd_def  {command} {fmt_lst_item [fmt_cmd $command]}

c_pass 1 fmt_arg_def {type name {mode {}}} NOP
c_pass 2 fmt_arg_def {type name {mode {}}} {
    set text "$type [fmt_arg $name]"
    if {$mode != {}} {append text " ($mode)"}
    fmt_lst_item $text
    return
}

c_pass 1 fmt_opt_def {name {arg {}}} NOP
c_pass 2 fmt_opt_def {name {arg {}}} {
    set text [fmt_option $name]
    if {$arg != {}} {append text " $arg"}
    fmt_lst_item $text
    return
}

c_pass 1 fmt_tkoption_def {name dbname dbclass} NOP
c_pass 2 fmt_tkoption_def {name dbname dbclass} {
    set    text ""
    append text "Command-Line Switch:\t[fmt_option $name]\n"
    append text "Database Name:\t[strong $dbname]\n"
    append text "Database Class:\t[strong $dbclass]\n"
    fmt_lst_item $text
}

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

c_pass 1 fmt_example_begin {} NOP
c_pass 2 fmt_example_begin {} {
    global currentEnv para
    if {[info exists currentEnv(_definition)]} {
	CloseParagraph $currentEnv(_definition)
    } elseif {[info exists currentEnv(pcount)]} {
	if {$para != {}} {
	    if {$currentEnv(pcount) == 0} {CloseParagraph $currentEnv(_first)}
	    if {$currentEnv(pcount) >  0} {CloseParagraph $currentEnv(_next)}
	    incr currentEnv(pcount)
	}
    } else {
	CloseParagraph
    }
    return
}

c_pass 1 fmt_example_end {} NOP
c_pass 2 fmt_example_end {} {
    global currentEnv para
    set penv {}
    if {[info exists currentEnv(_definition)]} {
	set penv $currentEnv(_definition)
    } elseif {[info exists currentEnv(pcount)]} {
	if {$currentEnv(pcount) == 0} {set penv $currentEnv(_first)}
	if {$currentEnv(pcount) >  0} {set penv $currentEnv(_next)}
	incr currentEnv(pcount)
    }
    if {$penv != {}} {
	# Save current list context, get chosen paragraph context and
	# then create an example context form this. After closing the
	# paragraph we get back our main list context.

	SaveContext
	SetContext $penv
	CloseParagraph [Example]
	RestoreContext
    } else {
	CloseParagraph [Example]
    }
    return
}

c_pass 1 fmt_example {code} NOP
c_pass 2 fmt_example {code} {
    fmt_example_begin
    fmt_plain_text $code
    fmt_example_end
    return
}

c_pass 1 fmt_nl {} NOP
c_pass 2 fmt_nl {} {
    global currentEnv
    if {[info exists currentEnv(_definition)]} {
	CloseParagraph $currentEnv(_definition)
    } else {
	if {$currentEnv(pcount) == 0} {CloseParagraph $currentEnv(_first)}
	if {$currentEnv(pcount) >  0} {CloseParagraph $currentEnv(_next)}
	incr currentEnv(pcount)
    }
    return
}

################################################################
# Visual markup of words and phrases.

proc fmt_arg     {text} {return $text}
proc fmt_cmd     {text} {return $text}
proc fmt_emph	 {text} {em     $text }
proc fmt_opt     {text} {return "?$text?" }
proc fmt_comment {text} {return}
proc fmt_sectref {text {label {}}} {
    if {![string length $label]} {set label $text}
    return "-> $text"
}
proc fmt_syscmd  {text} {strong $text}
proc fmt_method  {text} {return $text}
proc fmt_option  {text} {return $text}
proc fmt_widget  {text} {strong $text}
proc fmt_fun     {text} {strong $text}
proc fmt_type    {text} {strong $text}
proc fmt_package {text} {strong $text}
proc fmt_class   {text} {strong $text}
proc fmt_var     {text} {strong $text}
proc fmt_file    {text} {return "\"$text\""}
proc fmt_namespace     {text} {strong $text}
proc fmt_uri     {text {label {}}} {
    if {$label == {}} {
	# Without label we use the link directly as part of the text.
	return "<URL:$text>"
    } else {
	return "[em $label] <URL:$text>"
    }
}
proc fmt_term    {text} {em     $text}
proc fmt_const   {text} {strong $text}

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