sl@0: # man2help2.tcl -- sl@0: # sl@0: # This file defines procedures that are used during the second pass of sl@0: # the man page conversion. It converts the man format input to rtf sl@0: # form suitable for use by the Windows help compiler. sl@0: # sl@0: # Copyright (c) 1996 by Sun Microsystems, Inc. sl@0: # sl@0: # See the file "license.terms" for information on usage and redistribution sl@0: # of this file, and for a DISCLAIMER OF ALL WARRANTIES. sl@0: # sl@0: # RCS: @(#) $Id: man2help2.tcl,v 1.12 2002/10/03 13:34:32 dkf Exp $ sl@0: # sl@0: sl@0: # Global variables used by these scripts: sl@0: # sl@0: # state - state variable that controls action of text proc. sl@0: # sl@0: # topics - array indexed by (package,section,topic) with value sl@0: # of topic ID. sl@0: # sl@0: # keywords - array indexed by keyword string with value of topic ID. sl@0: # sl@0: # curID - current topic ID, starts at 0 and is incremented for sl@0: # each new topic file. sl@0: # sl@0: # curPkg - current package name (e.g. Tcl). sl@0: # sl@0: # curSect - current section title (e.g. "Tcl Built-In Commands"). sl@0: # sl@0: sl@0: # initGlobals -- sl@0: # sl@0: # This procedure is invoked to set the initial values of all of the sl@0: # global variables, before processing a man page. sl@0: # sl@0: # Arguments: sl@0: # None. sl@0: sl@0: proc initGlobals {} { sl@0: uplevel \#0 unset state sl@0: global state chars sl@0: sl@0: set state(paragraphPending) 0 sl@0: set state(breakPending) 0 sl@0: set state(firstIndent) 0 sl@0: set state(leftIndent) 0 sl@0: sl@0: set state(inTP) 0 sl@0: set state(paragraph) 0 sl@0: set state(textState) 0 sl@0: set state(curFont) "" sl@0: set state(startCode) "{\\b " sl@0: set state(startEmphasis) "{\\i " sl@0: set state(endCode) "}" sl@0: set state(endEmphasis) "}" sl@0: set state(noFill) 0 sl@0: set state(charCnt) 0 sl@0: set state(offset) [getTwips 0.5i] sl@0: set state(leftMargin) [getTwips 0.5i] sl@0: set state(nestingLevel) 0 sl@0: set state(intl) 0 sl@0: set state(sb) 0 sl@0: setTabs 0.5i sl@0: sl@0: # set up international character table sl@0: sl@0: array set chars { sl@0: o^ F4 sl@0: } sl@0: } sl@0: sl@0: sl@0: # beginFont -- sl@0: # sl@0: # Arranges for future text to use a special font, rather than sl@0: # the default paragraph font. sl@0: # sl@0: # Arguments: sl@0: # font - Name of new font to use. sl@0: sl@0: proc beginFont {font} { sl@0: global file state sl@0: sl@0: textSetup sl@0: if {[string equal $state(curFont) $font]} { sl@0: return sl@0: } sl@0: endFont sl@0: puts -nonewline $file $state(start$font) sl@0: set state(curFont) $font sl@0: } sl@0: sl@0: sl@0: # endFont -- sl@0: # sl@0: # Reverts to the default font for the paragraph type. sl@0: # sl@0: # Arguments: sl@0: # None. sl@0: sl@0: proc endFont {} { sl@0: global state file sl@0: sl@0: if {[string compare $state(curFont) ""]} { sl@0: puts -nonewline $file $state(end$state(curFont)) sl@0: set state(curFont) "" sl@0: } sl@0: } sl@0: sl@0: sl@0: # textSetup -- sl@0: # sl@0: # This procedure is called the first time that text is output for a sl@0: # paragraph. It outputs the header information for the paragraph. sl@0: # sl@0: # Arguments: sl@0: # None. sl@0: sl@0: proc textSetup {} { sl@0: global file state sl@0: sl@0: if $state(breakPending) { sl@0: puts $file "\\line" sl@0: } sl@0: if $state(paragraphPending) { sl@0: puts $file [format "\\par\n\\pard\\fi%.0f\\li%.0f" \ sl@0: $state(firstIndent) $state(leftIndent)] sl@0: foreach tab $state(tabs) { sl@0: puts $file [format "\\tx%.0f" $tab] sl@0: } sl@0: set state(tabs) {} sl@0: if {$state(sb)} { sl@0: puts $file "\\sb$state(sb)" sl@0: set state(sb) 0 sl@0: } sl@0: } sl@0: set state(breakPending) 0 sl@0: set state(paragraphPending) 0 sl@0: } sl@0: sl@0: sl@0: # text -- sl@0: # sl@0: # This procedure adds text to the current state(paragraph). If this is sl@0: # the first text in the state(paragraph) then header information for the sl@0: # state(paragraph) is output before the text. sl@0: # sl@0: # Arguments: sl@0: # string - Text to output in the state(paragraph). sl@0: sl@0: proc text {string} { sl@0: global file state chars sl@0: sl@0: textSetup sl@0: set string [string map [list \ sl@0: "\\" "\\\\" \ sl@0: "\{" "\\\{" \ sl@0: "\}" "\\\}" \ sl@0: "\t" {\tab } \ sl@0: '' "\\rdblquote " \ sl@0: `` "\\ldblquote " \ sl@0: ] $string] sl@0: sl@0: # Check if this is the beginning of an international character string. sl@0: # If so, look up the sequence in the chars table and substitute the sl@0: # appropriate hex value. sl@0: sl@0: if {$state(intl)} { sl@0: if {[regexp {^'([^']*)'} $string dummy ch]} { sl@0: if {[info exists chars($ch)]} { sl@0: regsub {^'[^']*'} $string "\\\\'$chars($ch)" string sl@0: } else { sl@0: puts stderr "Unknown international character '$ch'" sl@0: } sl@0: } sl@0: set state(intl) 0 sl@0: } sl@0: sl@0: switch $state(textState) { sl@0: REF { sl@0: if {$state(inTP) == 0} { sl@0: set string [insertRef $string] sl@0: } sl@0: } sl@0: SEE { sl@0: global topics curPkg curSect sl@0: foreach i [split $string] { sl@0: if {![regexp -nocase {^[a-z_0-9]+} [string trim $i] i ]} { sl@0: continue sl@0: } sl@0: if {![catch {set ref $topics($curPkg,$curSect,$i)} ]} { sl@0: regsub $i $string [link $i $ref] string sl@0: } sl@0: } sl@0: } sl@0: KEY { sl@0: return sl@0: } sl@0: } sl@0: puts -nonewline $file "$string" sl@0: } sl@0: sl@0: sl@0: sl@0: # insertRef -- sl@0: # sl@0: # This procedure looks for a string in the cross reference table and sl@0: # generates a hot-link to the appropriate topic. Tries to find the sl@0: # nearest reference in the manual. sl@0: # sl@0: # Arguments: sl@0: # string - Text to output in the state(paragraph). sl@0: sl@0: proc insertRef {string} { sl@0: global NAME_file curPkg curSect topics curID sl@0: set path {} sl@0: set string [string trim $string] sl@0: set ref {} sl@0: if {[info exists topics($curPkg,$curSect,$string)]} { sl@0: set ref $topics($curPkg,$curSect,$string) sl@0: } else { sl@0: set sites [array names topics "$curPkg,*,$string"] sl@0: set count [llength $sites] sl@0: if {$count > 0} { sl@0: set ref $topics([lindex $sites 0]) sl@0: } else { sl@0: set sites [array names topics "*,*,$string"] sl@0: set count [llength $sites] sl@0: if {$count > 0} { sl@0: set ref $topics([lindex $sites 0]) sl@0: } sl@0: } sl@0: } sl@0: sl@0: if {($ref != {}) && ($ref != $curID)} { sl@0: set string [link $string $ref] sl@0: } sl@0: return $string sl@0: } sl@0: sl@0: sl@0: sl@0: # macro -- sl@0: # sl@0: # This procedure is invoked to process macro invocations that start sl@0: # with "." (instead of '). sl@0: # sl@0: # Arguments: sl@0: # name - The name of the macro (without the "."). sl@0: # args - Any additional arguments to the macro. sl@0: sl@0: proc macro {name args} { sl@0: global state file sl@0: switch $name { sl@0: AP { sl@0: if {[llength $args] != 3 && [llength $args] != 2} { sl@0: puts stderr "Bad .AP macro: .$name [join $args " "]" sl@0: } sl@0: newPara 3.75i -3.75i sl@0: setTabs {1.25i 2.5i 3.75i} sl@0: font B sl@0: text [lindex $args 0] sl@0: tab sl@0: font I sl@0: text [lindex $args 1] sl@0: tab sl@0: font R sl@0: if {[llength $args] == 3} { sl@0: text "([lindex $args 2])" sl@0: } sl@0: tab sl@0: } sl@0: AS { sl@0: # next page and previous page sl@0: } sl@0: br { sl@0: lineBreak sl@0: } sl@0: BS {} sl@0: BE {} sl@0: CE { sl@0: puts -nonewline $::file "\\f0\\fs20 " sl@0: set state(noFill) 0 sl@0: set state(breakPending) 0 sl@0: newPara "" sl@0: set state(leftIndent) [expr {$state(leftIndent) - $state(offset)}] sl@0: set state(sb) 80 sl@0: } sl@0: CS { sl@0: # code section sl@0: set state(noFill) 1 sl@0: newPara "" sl@0: set state(leftIndent) [expr {$state(leftIndent) + $state(offset)}] sl@0: set state(sb) 80 sl@0: puts -nonewline $::file "\\f1\\fs18 " sl@0: } sl@0: DE { sl@0: set state(noFill) 0 sl@0: decrNestingLevel sl@0: newPara 0i sl@0: } sl@0: DS { sl@0: set state(noFill) 1 sl@0: incrNestingLevel sl@0: newPara 0i sl@0: } sl@0: fi { sl@0: set state(noFill) 0 sl@0: } sl@0: IP { sl@0: IPmacro $args sl@0: } sl@0: LP { sl@0: newPara 0i sl@0: set state(sb) 80 sl@0: } sl@0: ne { sl@0: } sl@0: nf { sl@0: set state(noFill) 1 sl@0: } sl@0: OP { sl@0: if {[llength $args] != 3} { sl@0: puts stderr "Bad .OP macro: .$name [join $args " "]" sl@0: } sl@0: set state(nestingLevel) 0 sl@0: newPara 0i sl@0: set state(sb) 120 sl@0: setTabs 4c sl@0: text "Command-Line Name:" sl@0: tab sl@0: font B sl@0: set x [lindex $args 0] sl@0: regsub -all {\\-} $x - x sl@0: text $x sl@0: lineBreak sl@0: font R sl@0: text "Database Name:" sl@0: tab sl@0: font B sl@0: text [lindex $args 1] sl@0: lineBreak sl@0: font R sl@0: text "Database Class:" sl@0: tab sl@0: font B sl@0: text [lindex $args 2] sl@0: font R sl@0: set state(inTP) 0 sl@0: newPara 0.5i sl@0: set state(sb) 80 sl@0: } sl@0: PP { sl@0: newPara 0i sl@0: set state(sb) 120 sl@0: } sl@0: RE { sl@0: decrNestingLevel sl@0: } sl@0: RS { sl@0: incrNestingLevel sl@0: } sl@0: SE { sl@0: font R sl@0: set state(noFill) 0 sl@0: set state(nestingLevel) 0 sl@0: newPara 0i sl@0: text "See the " sl@0: font B sl@0: set temp $state(textState) sl@0: set state(textState) REF sl@0: text options sl@0: set state(textState) $temp sl@0: font R sl@0: text " manual entry for detailed descriptions of the above options." sl@0: } sl@0: SH { sl@0: SHmacro $args sl@0: } sl@0: SO { sl@0: SHmacro "STANDARD OPTIONS" sl@0: set state(nestingLevel) 0 sl@0: newPara 0i sl@0: setTabs {4c 8c 12c} sl@0: font B sl@0: set state(noFill) 1 sl@0: } sl@0: so { sl@0: if {$args != "man.macros"} { sl@0: puts stderr "Unknown macro: .$name [join $args " "]" sl@0: } sl@0: } sl@0: sp { ;# needs work sl@0: if {$args == ""} { sl@0: set count 1 sl@0: } else { sl@0: set count [lindex $args 0] sl@0: } sl@0: while {$count > 0} { sl@0: lineBreak sl@0: incr count -1 sl@0: } sl@0: } sl@0: ta { sl@0: setTabs $args sl@0: } sl@0: TH { sl@0: THmacro $args sl@0: } sl@0: TP { sl@0: TPmacro $args sl@0: } sl@0: UL { ;# underline sl@0: puts -nonewline $file "{\\ul " sl@0: text [lindex $args 0] sl@0: puts -nonewline $file "}" sl@0: if {[llength $args] == 2} { sl@0: text [lindex $args 1] sl@0: } sl@0: } sl@0: VE {} sl@0: VS {} sl@0: default { sl@0: puts stderr "Unknown macro: .$name [join $args " "]" sl@0: } sl@0: } sl@0: } sl@0: sl@0: sl@0: # link -- sl@0: # sl@0: # This procedure returns the string for a hot link to a different sl@0: # context location. sl@0: # sl@0: # Arguments: sl@0: # label - String to display in hot-spot. sl@0: # id - Context string to jump to. sl@0: sl@0: proc link {label id} { sl@0: return "{\\uldb $label}{\\v $id}" sl@0: } sl@0: sl@0: sl@0: # font -- sl@0: # sl@0: # This procedure is invoked to handle font changes in the text sl@0: # being output. sl@0: # sl@0: # Arguments: sl@0: # type - Type of font: R, I, B, or S. sl@0: sl@0: proc font {type} { sl@0: global state sl@0: switch $type { sl@0: P - sl@0: R { sl@0: endFont sl@0: if {$state(textState) == "REF"} { sl@0: set state(textState) INSERT sl@0: } sl@0: } sl@0: C - sl@0: B { sl@0: beginFont Code sl@0: if {$state(textState) == "INSERT"} { sl@0: set state(textState) REF sl@0: } sl@0: } sl@0: I { sl@0: beginFont Emphasis sl@0: } sl@0: S { sl@0: } sl@0: default { sl@0: puts stderr "Unknown font: $type" sl@0: } sl@0: } sl@0: } sl@0: sl@0: sl@0: sl@0: # formattedText -- sl@0: # sl@0: # Insert a text string that may also have \fB-style font changes sl@0: # and a few other backslash sequences in it. sl@0: # sl@0: # Arguments: sl@0: # text - Text to insert. sl@0: sl@0: proc formattedText {text} { sl@0: global chars sl@0: sl@0: while {$text != ""} { sl@0: set index [string first \\ $text] sl@0: if {$index < 0} { sl@0: text $text sl@0: return sl@0: } sl@0: text [string range $text 0 [expr {$index-1}]] sl@0: set c [string index $text [expr {$index+1}]] sl@0: switch -- $c { sl@0: f { sl@0: font [string index $text [expr {$index+2}]] sl@0: set text [string range $text [expr {$index+3}] end] sl@0: } sl@0: e { sl@0: text "\\" sl@0: set text [string range $text [expr {$index+2}] end] sl@0: } sl@0: - { sl@0: dash sl@0: set text [string range $text [expr {$index+2}] end] sl@0: } sl@0: | { sl@0: set text [string range $text [expr {$index+2}] end] sl@0: } sl@0: o { sl@0: text "\\'" sl@0: regexp {'([^']*)'(.*)} $text all ch text sl@0: text $chars($ch) sl@0: } sl@0: default { sl@0: puts stderr "Unknown sequence: \\$c" sl@0: set text [string range $text [expr {$index+2}] end] sl@0: } sl@0: } sl@0: } sl@0: } sl@0: sl@0: sl@0: # dash -- sl@0: # sl@0: # This procedure is invoked to handle dash characters ("\-" in sl@0: # troff). It outputs a special dash character. sl@0: # sl@0: # Arguments: sl@0: # None. sl@0: sl@0: proc dash {} { sl@0: global state sl@0: if {[string equal $state(textState) "NAME"]} { sl@0: set state(textState) 0 sl@0: } sl@0: text "-" sl@0: } sl@0: sl@0: sl@0: # tab -- sl@0: # sl@0: # This procedure is invoked to handle tabs in the troff input. sl@0: # Right now it does nothing. sl@0: # sl@0: # Arguments: sl@0: # None. sl@0: sl@0: proc tab {} { sl@0: global file sl@0: sl@0: textSetup sl@0: puts -nonewline $file "\\tab " sl@0: } sl@0: sl@0: sl@0: # setTabs -- sl@0: # sl@0: # This procedure handles the ".ta" macro, which sets tab stops. sl@0: # sl@0: # Arguments: sl@0: # tabList - List of tab stops, each consisting of a number sl@0: # followed by "i" (inch) or "c" (cm). sl@0: sl@0: proc setTabs {tabList} { sl@0: global file state sl@0: sl@0: set state(tabs) {} sl@0: foreach arg $tabList { sl@0: set distance [expr {$state(leftMargin) \ sl@0: + ($state(offset) * $state(nestingLevel)) + [getTwips $arg]}] sl@0: lappend state(tabs) [expr {round($distance)}] sl@0: } sl@0: } sl@0: sl@0: sl@0: sl@0: # lineBreak -- sl@0: # sl@0: # Generates a line break in the HTML output. sl@0: # sl@0: # Arguments: sl@0: # None. sl@0: sl@0: proc lineBreak {} { sl@0: global state sl@0: textSetup sl@0: set state(breakPending) 1 sl@0: } sl@0: sl@0: sl@0: sl@0: # newline -- sl@0: # sl@0: # This procedure is invoked to handle newlines in the troff input. sl@0: # It outputs either a space character or a newline character, depending sl@0: # on fill mode. sl@0: # sl@0: # Arguments: sl@0: # None. sl@0: sl@0: proc newline {} { sl@0: global state sl@0: sl@0: if {$state(inTP)} { sl@0: set state(inTP) 0 sl@0: lineBreak sl@0: } elseif {$state(noFill)} { sl@0: lineBreak sl@0: } else { sl@0: text " " sl@0: } sl@0: } sl@0: sl@0: sl@0: # pageBreak -- sl@0: # sl@0: # This procedure is invoked to generate a page break. sl@0: # sl@0: # Arguments: sl@0: # None. sl@0: sl@0: proc pageBreak {} { sl@0: global file curVer sl@0: if {[string equal $curVer ""]} { sl@0: puts $file {\page} sl@0: } else { sl@0: puts $file {\par} sl@0: puts $file {\pard\sb400\qc} sl@0: puts $file "Last change: $curVer\\page" sl@0: } sl@0: } sl@0: sl@0: sl@0: # char -- sl@0: # sl@0: # This procedure is called to handle a special character. sl@0: # sl@0: # Arguments: sl@0: # name - Special character named in troff \x or \(xx construct. sl@0: sl@0: proc char {name} { sl@0: global file state sl@0: sl@0: switch -exact $name { sl@0: \\o { sl@0: set state(intl) 1 sl@0: } sl@0: \\\ { sl@0: textSetup sl@0: puts -nonewline $file " " sl@0: } sl@0: \\0 { sl@0: textSetup sl@0: puts -nonewline $file " \\emspace " sl@0: } sl@0: \\\\ { sl@0: textSetup sl@0: puts -nonewline $file "\\\\" sl@0: } sl@0: \\(+- { sl@0: textSetup sl@0: puts -nonewline $file "\\'b1 " sl@0: } sl@0: \\% - sl@0: \\| { sl@0: } sl@0: \\(bu { sl@0: textSetup sl@0: puts -nonewline $file "·" sl@0: } sl@0: default { sl@0: puts stderr "Unknown character: $name" sl@0: } sl@0: } sl@0: } sl@0: sl@0: sl@0: # macro2 -- sl@0: # sl@0: # This procedure handles macros that are invoked with a leading "'" sl@0: # character instead of space. Right now it just generates an sl@0: # error diagnostic. sl@0: # sl@0: # Arguments: sl@0: # name - The name of the macro (without the "."). sl@0: # args - Any additional arguments to the macro. sl@0: sl@0: proc macro2 {name args} { sl@0: puts stderr "Unknown macro: '$name [join $args " "]" sl@0: } sl@0: sl@0: sl@0: sl@0: # SHmacro -- sl@0: # sl@0: # Subsection head; handles the .SH macro. sl@0: # sl@0: # Arguments: sl@0: # name - Section name. sl@0: sl@0: proc SHmacro {argList} { sl@0: global file state sl@0: sl@0: set args [join $argList " "] sl@0: if {[llength $argList] < 1} { sl@0: puts stderr "Bad .SH macro: .SH $args" sl@0: } sl@0: sl@0: # control what the text proc does with text sl@0: sl@0: switch $args { sl@0: NAME {set state(textState) NAME} sl@0: DESCRIPTION {set state(textState) INSERT} sl@0: INTRODUCTION {set state(textState) INSERT} sl@0: "WIDGET-SPECIFIC OPTIONS" {set state(textState) INSERT} sl@0: "SEE ALSO" {set state(textState) SEE} sl@0: KEYWORDS {set state(textState) KEY; return} sl@0: } sl@0: sl@0: if {$state(breakPending) != -1} { sl@0: set state(breakPending) 1 sl@0: } else { sl@0: set state(breakPending) 0 sl@0: } sl@0: set state(noFill) 0 sl@0: nextPara 0i sl@0: font B sl@0: text $args sl@0: font R sl@0: nextPara .5i sl@0: } sl@0: sl@0: sl@0: sl@0: # IPmacro -- sl@0: # sl@0: # This procedure is invoked to handle ".IP" macros, which may take any sl@0: # of the following forms: sl@0: # sl@0: # .IP [1] Translate to a "1Step" state(paragraph). sl@0: # .IP [x] (x > 1) Translate to a "Step" state(paragraph). sl@0: # .IP Translate to a "Bullet" state(paragraph). sl@0: # .IP text count Translate to a FirstBody state(paragraph) with special sl@0: # indent and tab stop based on "count", and tab after sl@0: # "text". sl@0: # sl@0: # Arguments: sl@0: # argList - List of arguments to the .IP macro. sl@0: # sl@0: # HTML limitations: 'count' in '.IP text count' is ignored. sl@0: sl@0: proc IPmacro {argList} { sl@0: global file state sl@0: sl@0: set length [llength $argList] sl@0: if {$length == 0} { sl@0: newPara 0.5i sl@0: return sl@0: } sl@0: if {$length == 1} { sl@0: newPara 0.5i -0.5i sl@0: set state(sb) 80 sl@0: setTabs 0.5i sl@0: formattedText [lindex $argList 0] sl@0: tab sl@0: return sl@0: } sl@0: if {$length == 2} { sl@0: set count [lindex $argList 1] sl@0: set tab [expr $count * 0.1]i sl@0: newPara $tab -$tab sl@0: set state(sb) 80 sl@0: setTabs $tab sl@0: formattedText [lindex $argList 0] sl@0: tab sl@0: return sl@0: } sl@0: puts stderr "Bad .IP macro: .IP [join $argList " "]" sl@0: } sl@0: sl@0: sl@0: # TPmacro -- sl@0: # sl@0: # This procedure is invoked to handle ".TP" macros, which may take any sl@0: # of the following forms: sl@0: # sl@0: # .TP x Translate to an state(indent)ed state(paragraph) with the sl@0: # specified state(indent) (in 100 twip units). sl@0: # .TP Translate to an state(indent)ed state(paragraph) with sl@0: # default state(indent). sl@0: # sl@0: # Arguments: sl@0: # argList - List of arguments to the .IP macro. sl@0: # sl@0: # HTML limitations: 'x' in '.TP x' is ignored. sl@0: sl@0: proc TPmacro {argList} { sl@0: global state sl@0: set length [llength $argList] sl@0: if {$length == 0} { sl@0: set val 0.5i sl@0: } else { sl@0: set val [expr {([lindex $argList 0] * 100.0)/1440}]i sl@0: } sl@0: newPara $val -$val sl@0: setTabs $val sl@0: set state(inTP) 1 sl@0: set state(sb) 120 sl@0: } sl@0: sl@0: sl@0: # THmacro -- sl@0: # sl@0: # This procedure handles the .TH macro. It generates the non-scrolling sl@0: # header section for a given man page, and enters information into the sl@0: # table of contents. The .TH macro has the following form: sl@0: # sl@0: # .TH name section date footer header sl@0: # sl@0: # Arguments: sl@0: # argList - List of arguments to the .TH macro. sl@0: sl@0: proc THmacro {argList} { sl@0: global file curPkg curSect curID id_keywords state curVer bitmap sl@0: sl@0: if {[llength $argList] != 5} { sl@0: set args [join $argList " "] sl@0: puts stderr "Bad .TH macro: .TH $args" sl@0: } sl@0: incr curID sl@0: set name [lindex $argList 0] ;# Tcl_UpVar sl@0: set page [lindex $argList 1] ;# 3 sl@0: set curVer [lindex $argList 2] ;# 7.4 sl@0: set curPkg [lindex $argList 3] ;# Tcl sl@0: set curSect [lindex $argList 4] ;# {Tcl Library Procedures} sl@0: sl@0: regsub -all {\\ } $curSect { } curSect ;# Clean up for [incr\ Tcl] sl@0: sl@0: puts $file "#{\\footnote $curID}" ;# Context string sl@0: puts $file "\${\\footnote $name}" ;# Topic title sl@0: set browse "${curSect}${name}" sl@0: regsub -all {[ _-]} $browse {} browse sl@0: puts $file "+{\\footnote $browse}" ;# Browse sequence sl@0: sl@0: # Suppress duplicates sl@0: foreach i $id_keywords($curID) { sl@0: set keys($i) 1 sl@0: } sl@0: foreach i [array names keys] { sl@0: set i [string trim $i] sl@0: if {[string length $i] > 0} { sl@0: puts $file "K{\\footnote $i}" ;# Keyword strings sl@0: } sl@0: } sl@0: unset keys sl@0: puts $file "\\pard\\tx3000\\sb100\\sa100\\fs24\\keepn" sl@0: font B sl@0: text $name sl@0: tab sl@0: text $curSect sl@0: font R sl@0: if {[info exists bitmap]} { sl@0: # a right justified bitmap sl@0: puts $file "\\\{bmrt $bitmap\\\}" sl@0: } sl@0: puts $file "\\fs20" sl@0: set state(breakPending) -1 sl@0: } sl@0: sl@0: # nextPara -- sl@0: # sl@0: # Set the indents for a new paragraph, and start a paragraph break sl@0: # sl@0: # Arguments: sl@0: # leftIndent - The new left margin for body lines. sl@0: # firstIndent - The offset from the left margin for the first line. sl@0: sl@0: proc nextPara {leftIndent {firstIndent 0i}} { sl@0: global state sl@0: set state(leftIndent) [getTwips $leftIndent] sl@0: set state(firstIndent) [getTwips $firstIndent] sl@0: set state(paragraphPending) 1 sl@0: } sl@0: sl@0: sl@0: # newPara -- sl@0: # sl@0: # This procedure sets the left and hanging state(indent)s for a line. sl@0: # State(Indent)s are specified in units of inches or centimeters, and are sl@0: # relative to the current nesting level and left margin. sl@0: # sl@0: # Arguments: sl@0: # leftState(Indent) - The new left margin for lines after the first. sl@0: # firstState(Indent) - The new left margin for the first line of a state(paragraph). sl@0: sl@0: proc newPara {leftIndent {firstIndent 0i}} { sl@0: global state file sl@0: if $state(paragraph) { sl@0: puts -nonewline $file "\\line\n" sl@0: } sl@0: if {$leftIndent != ""} { sl@0: set state(leftIndent) [expr {$state(leftMargin) \ sl@0: + ($state(offset) * $state(nestingLevel)) \ sl@0: + [getTwips $leftIndent]}] sl@0: } sl@0: set state(firstIndent) [getTwips $firstIndent] sl@0: set state(paragraphPending) 1 sl@0: } sl@0: sl@0: sl@0: # getTwips -- sl@0: # sl@0: # This procedure converts a distance in inches or centimeters into sl@0: # twips (1/1440 of an inch). sl@0: # sl@0: # Arguments: sl@0: # arg - A number followed by "i" or "c" sl@0: sl@0: proc getTwips {arg} { sl@0: if {[scan $arg "%f%s" distance units] != 2} { sl@0: puts stderr "bad distance \"$arg\"" sl@0: return 0 sl@0: } sl@0: switch -- $units { sl@0: c { sl@0: set distance [expr {$distance * 567}] sl@0: } sl@0: i { sl@0: set distance [expr {$distance * 1440}] sl@0: } sl@0: default { sl@0: puts stderr "bad units in distance \"$arg\"" sl@0: continue sl@0: } sl@0: } sl@0: return $distance sl@0: } sl@0: sl@0: # incrNestingLevel -- sl@0: # sl@0: # This procedure does the work of the .RS macro, which increments sl@0: # the number of state(indent)ations that affect things like .PP. sl@0: # sl@0: # Arguments: sl@0: # None. sl@0: sl@0: proc incrNestingLevel {} { sl@0: global state sl@0: sl@0: incr state(nestingLevel) sl@0: set oldp $state(paragraph) sl@0: set state(paragraph) 0 sl@0: newPara 0i sl@0: set state(paragraph) $oldp sl@0: } sl@0: sl@0: # decrNestingLevel -- sl@0: # sl@0: # This procedure does the work of the .RE macro, which decrements sl@0: # the number of indentations that affect things like .PP. sl@0: # sl@0: # Arguments: sl@0: # None. sl@0: sl@0: proc decrNestingLevel {} { sl@0: global state sl@0: sl@0: if {$state(nestingLevel) == 0} { sl@0: puts stderr "Nesting level decremented below 0" sl@0: } else { sl@0: incr state(nestingLevel) -1 sl@0: } sl@0: } sl@0: