os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/tools/man2help2.tcl
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
# man2help2.tcl --
sl@0
     2
#
sl@0
     3
# This file defines procedures that are used during the second pass of
sl@0
     4
# the man page conversion.  It converts the man format input to rtf
sl@0
     5
# form suitable for use by the Windows help compiler.
sl@0
     6
#
sl@0
     7
# Copyright (c) 1996 by Sun Microsystems, Inc.
sl@0
     8
#
sl@0
     9
# See the file "license.terms" for information on usage and redistribution
sl@0
    10
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
sl@0
    11
# 
sl@0
    12
# RCS: @(#) $Id: man2help2.tcl,v 1.12 2002/10/03 13:34:32 dkf Exp $
sl@0
    13
# 
sl@0
    14
sl@0
    15
# Global variables used by these scripts:
sl@0
    16
#
sl@0
    17
# state -	state variable that controls action of text proc.
sl@0
    18
#				
sl@0
    19
# topics -	array indexed by (package,section,topic) with value
sl@0
    20
# 		of topic ID.
sl@0
    21
#
sl@0
    22
# keywords -	array indexed by keyword string with value of topic ID.
sl@0
    23
#
sl@0
    24
# curID - 	current topic ID, starts at 0 and is incremented for
sl@0
    25
# 		each new topic file.
sl@0
    26
#
sl@0
    27
# curPkg -	current package name (e.g. Tcl).
sl@0
    28
#
sl@0
    29
# curSect -	current section title (e.g. "Tcl Built-In Commands").
sl@0
    30
#
sl@0
    31
sl@0
    32
# initGlobals --
sl@0
    33
#
sl@0
    34
# This procedure is invoked to set the initial values of all of the
sl@0
    35
# global variables, before processing a man page.
sl@0
    36
#
sl@0
    37
# Arguments:
sl@0
    38
# None.
sl@0
    39
sl@0
    40
proc initGlobals {} {
sl@0
    41
    uplevel \#0 unset state
sl@0
    42
    global state chars
sl@0
    43
sl@0
    44
    set state(paragraphPending) 0
sl@0
    45
    set state(breakPending) 0
sl@0
    46
    set state(firstIndent) 0
sl@0
    47
    set state(leftIndent) 0
sl@0
    48
sl@0
    49
    set state(inTP) 0
sl@0
    50
    set state(paragraph) 0
sl@0
    51
    set state(textState) 0
sl@0
    52
    set state(curFont) ""
sl@0
    53
    set state(startCode) "{\\b "
sl@0
    54
    set state(startEmphasis) "{\\i "
sl@0
    55
    set state(endCode) "}"
sl@0
    56
    set state(endEmphasis) "}"
sl@0
    57
    set state(noFill) 0
sl@0
    58
    set state(charCnt) 0
sl@0
    59
    set state(offset) [getTwips 0.5i]
sl@0
    60
    set state(leftMargin) [getTwips 0.5i]
sl@0
    61
    set state(nestingLevel) 0
sl@0
    62
    set state(intl) 0
sl@0
    63
    set state(sb) 0
sl@0
    64
    setTabs 0.5i
sl@0
    65
sl@0
    66
# set up international character table
sl@0
    67
sl@0
    68
    array set chars {
sl@0
    69
	o^ F4
sl@0
    70
    }
sl@0
    71
}
sl@0
    72
sl@0
    73
sl@0
    74
# beginFont --
sl@0
    75
#
sl@0
    76
# Arranges for future text to use a special font, rather than
sl@0
    77
# the default paragraph font.
sl@0
    78
#
sl@0
    79
# Arguments:
sl@0
    80
# font -		Name of new font to use.
sl@0
    81
sl@0
    82
proc beginFont {font} {
sl@0
    83
    global file state
sl@0
    84
sl@0
    85
    textSetup
sl@0
    86
    if {[string equal $state(curFont) $font]} {
sl@0
    87
	return
sl@0
    88
    }
sl@0
    89
    endFont
sl@0
    90
    puts -nonewline $file $state(start$font)
sl@0
    91
    set state(curFont) $font
sl@0
    92
}
sl@0
    93
sl@0
    94
sl@0
    95
# endFont --
sl@0
    96
#
sl@0
    97
# Reverts to the default font for the paragraph type.
sl@0
    98
#
sl@0
    99
# Arguments:
sl@0
   100
# None.
sl@0
   101
sl@0
   102
proc endFont {} {
sl@0
   103
    global state file
sl@0
   104
sl@0
   105
    if {[string compare $state(curFont) ""]} {
sl@0
   106
	puts -nonewline $file $state(end$state(curFont))
sl@0
   107
	set state(curFont) ""
sl@0
   108
    }
sl@0
   109
}
sl@0
   110
sl@0
   111
sl@0
   112
# textSetup --
sl@0
   113
#
sl@0
   114
# This procedure is called the first time that text is output for a
sl@0
   115
# paragraph.  It outputs the header information for the paragraph.
sl@0
   116
#
sl@0
   117
# Arguments:
sl@0
   118
# None.
sl@0
   119
sl@0
   120
proc textSetup {} {
sl@0
   121
    global file state
sl@0
   122
sl@0
   123
    if $state(breakPending) {
sl@0
   124
	puts $file "\\line"
sl@0
   125
    }
sl@0
   126
    if $state(paragraphPending) {
sl@0
   127
	puts $file [format "\\par\n\\pard\\fi%.0f\\li%.0f" \
sl@0
   128
			$state(firstIndent) $state(leftIndent)]
sl@0
   129
	foreach tab $state(tabs) {
sl@0
   130
	    puts $file [format "\\tx%.0f" $tab]
sl@0
   131
	}
sl@0
   132
	set state(tabs) {}
sl@0
   133
	if {$state(sb)} {
sl@0
   134
	    puts $file "\\sb$state(sb)"
sl@0
   135
	    set state(sb) 0
sl@0
   136
	}
sl@0
   137
    }
sl@0
   138
    set state(breakPending) 0
sl@0
   139
    set state(paragraphPending) 0
sl@0
   140
}
sl@0
   141
sl@0
   142
sl@0
   143
# text --
sl@0
   144
#
sl@0
   145
# This procedure adds text to the current state(paragraph).  If this is
sl@0
   146
# the first text in the state(paragraph) then header information for the
sl@0
   147
# state(paragraph) is output before the text.
sl@0
   148
#
sl@0
   149
# Arguments:
sl@0
   150
# string -		Text to output in the state(paragraph).
sl@0
   151
sl@0
   152
proc text {string} {
sl@0
   153
    global file state chars
sl@0
   154
sl@0
   155
    textSetup
sl@0
   156
    set string [string map [list \
sl@0
   157
	    "\\"	"\\\\" \
sl@0
   158
	    "\{"	"\\\{" \
sl@0
   159
	    "\}"	"\\\}" \
sl@0
   160
	    "\t"	{\tab } \
sl@0
   161
	    ''		"\\rdblquote " \
sl@0
   162
	    ``		"\\ldblquote " \
sl@0
   163
	    ] $string]
sl@0
   164
sl@0
   165
    # Check if this is the beginning of an international character string.
sl@0
   166
    # If so, look up the sequence in the chars table and substitute the
sl@0
   167
    # appropriate hex value.
sl@0
   168
sl@0
   169
    if {$state(intl)} {
sl@0
   170
	if {[regexp {^'([^']*)'} $string dummy ch]} {
sl@0
   171
	    if {[info exists chars($ch)]} {
sl@0
   172
		regsub {^'[^']*'} $string "\\\\'$chars($ch)" string
sl@0
   173
	    } else {
sl@0
   174
		puts stderr "Unknown international character '$ch'"
sl@0
   175
	    }
sl@0
   176
	}
sl@0
   177
	set state(intl) 0
sl@0
   178
    }
sl@0
   179
sl@0
   180
    switch $state(textState) {
sl@0
   181
	REF { 
sl@0
   182
	    if {$state(inTP) == 0} {
sl@0
   183
		set string [insertRef $string]
sl@0
   184
	    }
sl@0
   185
	}
sl@0
   186
	SEE { 
sl@0
   187
	    global topics curPkg curSect
sl@0
   188
	    foreach i [split $string] {
sl@0
   189
		if {![regexp -nocase {^[a-z_0-9]+} [string trim $i] i ]} {
sl@0
   190
		    continue
sl@0
   191
		}
sl@0
   192
		if {![catch {set ref $topics($curPkg,$curSect,$i)} ]} {
sl@0
   193
		    regsub $i $string [link $i $ref] string
sl@0
   194
		}
sl@0
   195
	    }
sl@0
   196
	}
sl@0
   197
	KEY {
sl@0
   198
	    return
sl@0
   199
	}
sl@0
   200
    }
sl@0
   201
    puts -nonewline $file "$string"
sl@0
   202
}
sl@0
   203
sl@0
   204
sl@0
   205
sl@0
   206
# insertRef --
sl@0
   207
#
sl@0
   208
# This procedure looks for a string in the cross reference table and
sl@0
   209
# generates a hot-link to the appropriate topic.  Tries to find the
sl@0
   210
# nearest reference in the manual.
sl@0
   211
#
sl@0
   212
# Arguments:
sl@0
   213
# string -		Text to output in the state(paragraph).
sl@0
   214
sl@0
   215
proc insertRef {string} {
sl@0
   216
    global NAME_file curPkg curSect topics curID
sl@0
   217
    set path {}
sl@0
   218
    set string [string trim $string]
sl@0
   219
    set ref {}
sl@0
   220
    if {[info exists topics($curPkg,$curSect,$string)]} {
sl@0
   221
	set ref $topics($curPkg,$curSect,$string)
sl@0
   222
    } else {
sl@0
   223
	set sites [array names topics "$curPkg,*,$string"]
sl@0
   224
	set count [llength $sites]
sl@0
   225
	if {$count > 0} {
sl@0
   226
	    set ref $topics([lindex $sites 0])
sl@0
   227
	} else {
sl@0
   228
	    set sites [array names topics "*,*,$string"]
sl@0
   229
	    set count [llength $sites]
sl@0
   230
	    if {$count > 0} {
sl@0
   231
		set ref $topics([lindex $sites 0])
sl@0
   232
	    }
sl@0
   233
	}
sl@0
   234
    }
sl@0
   235
sl@0
   236
    if {($ref != {}) && ($ref != $curID)} {
sl@0
   237
	set string [link $string $ref]
sl@0
   238
    }
sl@0
   239
    return $string
sl@0
   240
}
sl@0
   241
sl@0
   242
sl@0
   243
sl@0
   244
# macro --
sl@0
   245
#
sl@0
   246
# This procedure is invoked to process macro invocations that start
sl@0
   247
# with "." (instead of ').
sl@0
   248
#
sl@0
   249
# Arguments:
sl@0
   250
# name -		The name of the macro (without the ".").
sl@0
   251
# args -		Any additional arguments to the macro.
sl@0
   252
sl@0
   253
proc macro {name args} {
sl@0
   254
    global state file
sl@0
   255
    switch $name {
sl@0
   256
	AP {
sl@0
   257
	    if {[llength $args] != 3 && [llength $args] != 2} {
sl@0
   258
		puts stderr "Bad .AP macro: .$name [join $args " "]"
sl@0
   259
	    }
sl@0
   260
	    newPara 3.75i -3.75i
sl@0
   261
	    setTabs {1.25i 2.5i 3.75i}
sl@0
   262
	    font B
sl@0
   263
	    text [lindex $args 0]
sl@0
   264
	    tab
sl@0
   265
	    font I
sl@0
   266
	    text [lindex $args 1]
sl@0
   267
	    tab
sl@0
   268
	    font R
sl@0
   269
	    if {[llength $args] == 3} {
sl@0
   270
		text "([lindex $args 2])"
sl@0
   271
	    }
sl@0
   272
	    tab
sl@0
   273
	}
sl@0
   274
	AS {
sl@0
   275
	    # next page and previous page
sl@0
   276
	}
sl@0
   277
	br {
sl@0
   278
	    lineBreak	
sl@0
   279
	}
sl@0
   280
	BS {}
sl@0
   281
	BE {}
sl@0
   282
	CE {
sl@0
   283
	    puts -nonewline $::file "\\f0\\fs20 "
sl@0
   284
	    set state(noFill) 0
sl@0
   285
	    set state(breakPending) 0
sl@0
   286
	    newPara ""
sl@0
   287
	    set state(leftIndent) [expr {$state(leftIndent) - $state(offset)}]
sl@0
   288
	    set state(sb) 80
sl@0
   289
	}
sl@0
   290
	CS {
sl@0
   291
	    # code section
sl@0
   292
	    set state(noFill) 1
sl@0
   293
	    newPara ""
sl@0
   294
	    set state(leftIndent) [expr {$state(leftIndent) + $state(offset)}]
sl@0
   295
	    set state(sb) 80
sl@0
   296
	    puts -nonewline $::file "\\f1\\fs18 "
sl@0
   297
	}
sl@0
   298
	DE {
sl@0
   299
	    set state(noFill) 0
sl@0
   300
	    decrNestingLevel
sl@0
   301
	    newPara 0i
sl@0
   302
	}
sl@0
   303
	DS {
sl@0
   304
	    set state(noFill) 1
sl@0
   305
	    incrNestingLevel
sl@0
   306
	    newPara 0i
sl@0
   307
	}
sl@0
   308
	fi {
sl@0
   309
	    set state(noFill) 0
sl@0
   310
	}
sl@0
   311
	IP {
sl@0
   312
	    IPmacro $args
sl@0
   313
	}
sl@0
   314
	LP {
sl@0
   315
	    newPara 0i
sl@0
   316
	    set state(sb) 80
sl@0
   317
	}
sl@0
   318
	ne {
sl@0
   319
	}
sl@0
   320
	nf {
sl@0
   321
	    set state(noFill) 1
sl@0
   322
	}
sl@0
   323
	OP {
sl@0
   324
	    if {[llength $args] != 3} {
sl@0
   325
		puts stderr "Bad .OP macro: .$name [join $args " "]"
sl@0
   326
	    }
sl@0
   327
	    set state(nestingLevel) 0
sl@0
   328
	    newPara 0i
sl@0
   329
	    set state(sb) 120
sl@0
   330
	    setTabs 4c
sl@0
   331
	    text "Command-Line Name:"
sl@0
   332
	    tab
sl@0
   333
	    font B
sl@0
   334
	    set x [lindex $args 0]
sl@0
   335
	    regsub -all {\\-} $x - x
sl@0
   336
	    text $x
sl@0
   337
	    lineBreak
sl@0
   338
	    font R
sl@0
   339
	    text "Database Name:"
sl@0
   340
	    tab
sl@0
   341
	    font B
sl@0
   342
	    text [lindex $args 1]
sl@0
   343
	    lineBreak
sl@0
   344
	    font R
sl@0
   345
	    text "Database Class:"
sl@0
   346
	    tab
sl@0
   347
	    font B
sl@0
   348
	    text [lindex $args 2]
sl@0
   349
	    font R
sl@0
   350
	    set state(inTP) 0
sl@0
   351
	    newPara 0.5i
sl@0
   352
	    set state(sb) 80
sl@0
   353
	}
sl@0
   354
	PP {
sl@0
   355
	    newPara 0i
sl@0
   356
	    set state(sb) 120
sl@0
   357
	}
sl@0
   358
	RE {
sl@0
   359
	    decrNestingLevel
sl@0
   360
	}
sl@0
   361
	RS {
sl@0
   362
	    incrNestingLevel
sl@0
   363
	}
sl@0
   364
	SE {
sl@0
   365
	    font R
sl@0
   366
	    set state(noFill) 0
sl@0
   367
	    set state(nestingLevel) 0
sl@0
   368
	    newPara 0i
sl@0
   369
	    text "See the "
sl@0
   370
	    font B
sl@0
   371
	    set temp $state(textState)
sl@0
   372
	    set state(textState) REF
sl@0
   373
	    text options
sl@0
   374
	    set state(textState) $temp
sl@0
   375
	    font R
sl@0
   376
	    text " manual entry for detailed descriptions of the above options."
sl@0
   377
	}
sl@0
   378
	SH {
sl@0
   379
	    SHmacro $args
sl@0
   380
	}
sl@0
   381
	SO {
sl@0
   382
	    SHmacro "STANDARD OPTIONS"
sl@0
   383
	    set state(nestingLevel) 0
sl@0
   384
	    newPara 0i
sl@0
   385
	    setTabs {4c 8c 12c}
sl@0
   386
	    font B
sl@0
   387
	    set state(noFill) 1
sl@0
   388
	}
sl@0
   389
	so {
sl@0
   390
	    if {$args != "man.macros"} {
sl@0
   391
		puts stderr "Unknown macro: .$name [join $args " "]"
sl@0
   392
	    }
sl@0
   393
	}
sl@0
   394
	sp {					;# needs work
sl@0
   395
	    if {$args == ""} {
sl@0
   396
		set count 1
sl@0
   397
	    } else {
sl@0
   398
		set count [lindex $args 0]
sl@0
   399
	    }
sl@0
   400
	    while {$count > 0} {
sl@0
   401
		lineBreak
sl@0
   402
		incr count -1
sl@0
   403
	    }
sl@0
   404
	}
sl@0
   405
	ta {
sl@0
   406
	    setTabs $args
sl@0
   407
	}
sl@0
   408
	TH {
sl@0
   409
	    THmacro $args
sl@0
   410
	}
sl@0
   411
	TP {
sl@0
   412
	    TPmacro $args
sl@0
   413
	}
sl@0
   414
	UL {					;# underline
sl@0
   415
	    puts -nonewline $file "{\\ul "
sl@0
   416
	    text [lindex $args 0]
sl@0
   417
	    puts -nonewline $file "}"
sl@0
   418
	    if {[llength $args] == 2} {
sl@0
   419
		text [lindex $args 1]
sl@0
   420
	    }
sl@0
   421
	}
sl@0
   422
	VE {}
sl@0
   423
	VS {}
sl@0
   424
	default {
sl@0
   425
	    puts stderr "Unknown macro: .$name [join $args " "]"
sl@0
   426
	}
sl@0
   427
    }
sl@0
   428
}
sl@0
   429
sl@0
   430
sl@0
   431
# link --
sl@0
   432
#
sl@0
   433
# This procedure returns the string for  a hot link to a different
sl@0
   434
# context location.
sl@0
   435
#
sl@0
   436
# Arguments:
sl@0
   437
# label -		String to display in hot-spot.
sl@0
   438
# id -			Context string to jump to.
sl@0
   439
sl@0
   440
proc link {label id} {
sl@0
   441
    return "{\\uldb $label}{\\v $id}"
sl@0
   442
}
sl@0
   443
sl@0
   444
sl@0
   445
# font --
sl@0
   446
#
sl@0
   447
# This procedure is invoked to handle font changes in the text
sl@0
   448
# being output.
sl@0
   449
#
sl@0
   450
# Arguments:
sl@0
   451
# type -		Type of font: R, I, B, or S.
sl@0
   452
sl@0
   453
proc font {type} {
sl@0
   454
    global state
sl@0
   455
    switch $type {
sl@0
   456
	P -
sl@0
   457
	R {
sl@0
   458
	    endFont
sl@0
   459
	    if {$state(textState) == "REF"} {
sl@0
   460
		set state(textState) INSERT
sl@0
   461
	    }
sl@0
   462
	}
sl@0
   463
	C -
sl@0
   464
	B {
sl@0
   465
	    beginFont Code
sl@0
   466
	    if {$state(textState) == "INSERT"} {
sl@0
   467
		set state(textState) REF
sl@0
   468
	    }
sl@0
   469
	}
sl@0
   470
	I {
sl@0
   471
	    beginFont Emphasis
sl@0
   472
	}
sl@0
   473
	S {
sl@0
   474
	}
sl@0
   475
	default {
sl@0
   476
	    puts stderr "Unknown font: $type"
sl@0
   477
	}
sl@0
   478
    }
sl@0
   479
}
sl@0
   480
sl@0
   481
sl@0
   482
sl@0
   483
# formattedText --
sl@0
   484
#
sl@0
   485
# Insert a text string that may also have \fB-style font changes
sl@0
   486
# and a few other backslash sequences in it.
sl@0
   487
#
sl@0
   488
# Arguments:
sl@0
   489
# text -		Text to insert.
sl@0
   490
sl@0
   491
proc formattedText {text} {
sl@0
   492
    global chars
sl@0
   493
sl@0
   494
    while {$text != ""} {
sl@0
   495
	set index [string first \\ $text]
sl@0
   496
	if {$index < 0} {
sl@0
   497
	    text $text
sl@0
   498
	    return
sl@0
   499
	}
sl@0
   500
	text [string range $text 0 [expr {$index-1}]]
sl@0
   501
	set c [string index $text [expr {$index+1}]]
sl@0
   502
	switch -- $c {
sl@0
   503
	    f {
sl@0
   504
		font [string index $text [expr {$index+2}]]
sl@0
   505
		set text [string range $text [expr {$index+3}] end]
sl@0
   506
	    }
sl@0
   507
	    e {
sl@0
   508
		text "\\"
sl@0
   509
		set text [string range $text [expr {$index+2}] end]
sl@0
   510
	    }
sl@0
   511
	    - {
sl@0
   512
		dash
sl@0
   513
		set text [string range $text [expr {$index+2}] end]
sl@0
   514
	    }
sl@0
   515
	    | {
sl@0
   516
		set text [string range $text [expr {$index+2}] end]
sl@0
   517
	    }
sl@0
   518
	    o {
sl@0
   519
		text "\\'"
sl@0
   520
		regexp {'([^']*)'(.*)} $text all ch text
sl@0
   521
		text $chars($ch)
sl@0
   522
	    }
sl@0
   523
	    default {
sl@0
   524
		puts stderr "Unknown sequence: \\$c"
sl@0
   525
		set text [string range $text [expr {$index+2}] end]
sl@0
   526
	    }
sl@0
   527
	}
sl@0
   528
    }
sl@0
   529
}
sl@0
   530
sl@0
   531
sl@0
   532
# dash --
sl@0
   533
#
sl@0
   534
# This procedure is invoked to handle dash characters ("\-" in
sl@0
   535
# troff).  It outputs a special dash character.
sl@0
   536
#
sl@0
   537
# Arguments:
sl@0
   538
# None.
sl@0
   539
sl@0
   540
proc dash {} {
sl@0
   541
    global state
sl@0
   542
    if {[string equal $state(textState) "NAME"]} {
sl@0
   543
    	set state(textState) 0
sl@0
   544
    }
sl@0
   545
    text "-"
sl@0
   546
}
sl@0
   547
sl@0
   548
sl@0
   549
# tab --
sl@0
   550
#
sl@0
   551
# This procedure is invoked to handle tabs in the troff input.
sl@0
   552
# Right now it does nothing.
sl@0
   553
#
sl@0
   554
# Arguments:
sl@0
   555
# None.
sl@0
   556
sl@0
   557
proc tab {} {
sl@0
   558
    global file
sl@0
   559
sl@0
   560
    textSetup
sl@0
   561
    puts -nonewline $file "\\tab "
sl@0
   562
}
sl@0
   563
sl@0
   564
sl@0
   565
# setTabs --
sl@0
   566
#
sl@0
   567
# This procedure handles the ".ta" macro, which sets tab stops.
sl@0
   568
#
sl@0
   569
# Arguments:
sl@0
   570
# tabList -	List of tab stops, each consisting of a number
sl@0
   571
#			followed by "i" (inch) or "c" (cm).
sl@0
   572
sl@0
   573
proc setTabs {tabList} {
sl@0
   574
    global file state
sl@0
   575
sl@0
   576
    set state(tabs) {}
sl@0
   577
    foreach arg $tabList {
sl@0
   578
	set distance [expr {$state(leftMargin) \
sl@0
   579
		+ ($state(offset) * $state(nestingLevel)) + [getTwips $arg]}]
sl@0
   580
	lappend state(tabs) [expr {round($distance)}]
sl@0
   581
    }
sl@0
   582
}
sl@0
   583
sl@0
   584
sl@0
   585
sl@0
   586
# lineBreak --
sl@0
   587
#
sl@0
   588
# Generates a line break in the HTML output.
sl@0
   589
#
sl@0
   590
# Arguments:
sl@0
   591
# None.
sl@0
   592
sl@0
   593
proc lineBreak {} {
sl@0
   594
    global state
sl@0
   595
    textSetup
sl@0
   596
    set state(breakPending) 1
sl@0
   597
}
sl@0
   598
sl@0
   599
sl@0
   600
sl@0
   601
# newline --
sl@0
   602
#
sl@0
   603
# This procedure is invoked to handle newlines in the troff input.
sl@0
   604
# It outputs either a space character or a newline character, depending
sl@0
   605
# on fill mode.
sl@0
   606
#
sl@0
   607
# Arguments:
sl@0
   608
# None.
sl@0
   609
sl@0
   610
proc newline {} {
sl@0
   611
    global state
sl@0
   612
sl@0
   613
    if {$state(inTP)} {
sl@0
   614
    	set state(inTP) 0
sl@0
   615
	lineBreak
sl@0
   616
    } elseif {$state(noFill)} {
sl@0
   617
	lineBreak
sl@0
   618
    } else {
sl@0
   619
	text " "
sl@0
   620
    }
sl@0
   621
}
sl@0
   622
sl@0
   623
sl@0
   624
# pageBreak --
sl@0
   625
#
sl@0
   626
# This procedure is invoked to generate a page break.
sl@0
   627
#
sl@0
   628
# Arguments:
sl@0
   629
# None.
sl@0
   630
sl@0
   631
proc pageBreak {} {
sl@0
   632
    global file curVer
sl@0
   633
    if {[string equal $curVer ""]} {
sl@0
   634
	puts $file {\page}
sl@0
   635
    } else {
sl@0
   636
	puts $file {\par}
sl@0
   637
	puts $file {\pard\sb400\qc}
sl@0
   638
	puts $file "Last change: $curVer\\page"
sl@0
   639
    }
sl@0
   640
}
sl@0
   641
sl@0
   642
sl@0
   643
# char --
sl@0
   644
#
sl@0
   645
# This procedure is called to handle a special character.
sl@0
   646
#
sl@0
   647
# Arguments:
sl@0
   648
# name -		Special character named in troff \x or \(xx construct.
sl@0
   649
sl@0
   650
proc char {name} {
sl@0
   651
    global file state
sl@0
   652
sl@0
   653
    switch -exact $name {
sl@0
   654
        \\o {
sl@0
   655
	    set state(intl) 1
sl@0
   656
	}
sl@0
   657
	\\\  {
sl@0
   658
	    textSetup
sl@0
   659
	    puts -nonewline $file " "
sl@0
   660
	}
sl@0
   661
	\\0 {
sl@0
   662
	    textSetup
sl@0
   663
	    puts -nonewline $file " \\emspace "
sl@0
   664
	}
sl@0
   665
	\\\\ {
sl@0
   666
	    textSetup
sl@0
   667
	    puts -nonewline $file "\\\\"
sl@0
   668
	}
sl@0
   669
	\\(+- {
sl@0
   670
	    textSetup
sl@0
   671
	    puts -nonewline $file "\\'b1 "
sl@0
   672
	}
sl@0
   673
	\\% -
sl@0
   674
	\\| {
sl@0
   675
	}
sl@0
   676
	\\(bu {
sl@0
   677
	    textSetup
sl@0
   678
	    puts -nonewline $file "·"
sl@0
   679
	}
sl@0
   680
	default {
sl@0
   681
	    puts stderr "Unknown character: $name"
sl@0
   682
	}
sl@0
   683
    }
sl@0
   684
}
sl@0
   685
sl@0
   686
sl@0
   687
# macro2 --
sl@0
   688
#
sl@0
   689
# This procedure handles macros that are invoked with a leading "'"
sl@0
   690
# character instead of space.  Right now it just generates an
sl@0
   691
# error diagnostic.
sl@0
   692
#
sl@0
   693
# Arguments:
sl@0
   694
# name -		The name of the macro (without the ".").
sl@0
   695
# args -		Any additional arguments to the macro.
sl@0
   696
sl@0
   697
proc macro2 {name args} {
sl@0
   698
    puts stderr "Unknown macro: '$name [join $args " "]"
sl@0
   699
}
sl@0
   700
sl@0
   701
sl@0
   702
sl@0
   703
# SHmacro --
sl@0
   704
#
sl@0
   705
# Subsection head; handles the .SH macro.
sl@0
   706
#
sl@0
   707
# Arguments:
sl@0
   708
# name -		Section name.
sl@0
   709
sl@0
   710
proc SHmacro {argList} {
sl@0
   711
    global file state
sl@0
   712
sl@0
   713
    set args [join $argList " "]
sl@0
   714
    if {[llength $argList] < 1} {
sl@0
   715
	puts stderr "Bad .SH macro: .SH $args"
sl@0
   716
    }
sl@0
   717
sl@0
   718
    # control what the text proc does with text
sl@0
   719
    
sl@0
   720
    switch $args {
sl@0
   721
	NAME {set state(textState) NAME}
sl@0
   722
	DESCRIPTION {set state(textState) INSERT}
sl@0
   723
	INTRODUCTION {set state(textState) INSERT}
sl@0
   724
	"WIDGET-SPECIFIC OPTIONS" {set state(textState) INSERT}
sl@0
   725
	"SEE ALSO" {set state(textState) SEE}
sl@0
   726
	KEYWORDS {set state(textState) KEY; return}
sl@0
   727
    }
sl@0
   728
sl@0
   729
    if {$state(breakPending) != -1} {
sl@0
   730
	set state(breakPending) 1
sl@0
   731
    } else {
sl@0
   732
	set state(breakPending) 0
sl@0
   733
    }
sl@0
   734
    set state(noFill) 0
sl@0
   735
    nextPara 0i
sl@0
   736
    font B
sl@0
   737
    text $args
sl@0
   738
    font R
sl@0
   739
    nextPara .5i
sl@0
   740
}
sl@0
   741
sl@0
   742
sl@0
   743
sl@0
   744
# IPmacro --
sl@0
   745
#
sl@0
   746
# This procedure is invoked to handle ".IP" macros, which may take any
sl@0
   747
# of the following forms:
sl@0
   748
#
sl@0
   749
# .IP [1]			Translate to a "1Step" state(paragraph).
sl@0
   750
# .IP [x] (x > 1)	Translate to a "Step" state(paragraph).
sl@0
   751
# .IP				Translate to a "Bullet" state(paragraph).
sl@0
   752
# .IP text count	Translate to a FirstBody state(paragraph) with special
sl@0
   753
#					indent and tab stop based on "count", and tab after
sl@0
   754
#					"text".
sl@0
   755
#
sl@0
   756
# Arguments:
sl@0
   757
# argList -		List of arguments to the .IP macro.
sl@0
   758
#
sl@0
   759
# HTML limitations: 'count' in '.IP text count' is ignored.
sl@0
   760
sl@0
   761
proc IPmacro {argList} {
sl@0
   762
    global file state
sl@0
   763
sl@0
   764
    set length [llength $argList]
sl@0
   765
    if {$length == 0} {
sl@0
   766
	newPara 0.5i
sl@0
   767
	return
sl@0
   768
    }
sl@0
   769
    if {$length == 1} {
sl@0
   770
	newPara 0.5i -0.5i
sl@0
   771
	set state(sb) 80
sl@0
   772
	setTabs 0.5i
sl@0
   773
	formattedText [lindex $argList 0]
sl@0
   774
	tab
sl@0
   775
	return
sl@0
   776
    }
sl@0
   777
    if {$length == 2} {
sl@0
   778
	set count [lindex $argList 1]
sl@0
   779
	set tab [expr $count * 0.1]i
sl@0
   780
	newPara $tab -$tab
sl@0
   781
	set state(sb) 80
sl@0
   782
	setTabs $tab
sl@0
   783
	formattedText [lindex $argList 0]
sl@0
   784
	tab
sl@0
   785
	return
sl@0
   786
    }
sl@0
   787
    puts stderr "Bad .IP macro: .IP [join $argList " "]"
sl@0
   788
}
sl@0
   789
sl@0
   790
sl@0
   791
# TPmacro --
sl@0
   792
#
sl@0
   793
# This procedure is invoked to handle ".TP" macros, which may take any
sl@0
   794
# of the following forms:
sl@0
   795
#
sl@0
   796
# .TP x		Translate to an state(indent)ed state(paragraph) with the
sl@0
   797
# 			specified state(indent) (in 100 twip units).
sl@0
   798
# .TP		Translate to an state(indent)ed state(paragraph) with
sl@0
   799
# 			default state(indent).
sl@0
   800
#
sl@0
   801
# Arguments:
sl@0
   802
# argList -		List of arguments to the .IP macro.
sl@0
   803
#
sl@0
   804
# HTML limitations: 'x' in '.TP x' is ignored.
sl@0
   805
sl@0
   806
proc TPmacro {argList} {
sl@0
   807
    global state
sl@0
   808
    set length [llength $argList]
sl@0
   809
    if {$length == 0} {
sl@0
   810
	set val 0.5i
sl@0
   811
    } else {
sl@0
   812
	set val [expr {([lindex $argList 0] * 100.0)/1440}]i
sl@0
   813
    }
sl@0
   814
    newPara $val -$val
sl@0
   815
    setTabs $val
sl@0
   816
    set state(inTP) 1
sl@0
   817
    set state(sb) 120
sl@0
   818
}
sl@0
   819
sl@0
   820
sl@0
   821
# THmacro --
sl@0
   822
#
sl@0
   823
# This procedure handles the .TH macro.  It generates the non-scrolling
sl@0
   824
# header section for a given man page, and enters information into the
sl@0
   825
# table of contents.  The .TH macro has the following form:
sl@0
   826
#
sl@0
   827
# .TH name section date footer header
sl@0
   828
#
sl@0
   829
# Arguments:
sl@0
   830
# argList -		List of arguments to the .TH macro.
sl@0
   831
sl@0
   832
proc THmacro {argList} {
sl@0
   833
    global file curPkg curSect curID id_keywords state curVer bitmap
sl@0
   834
sl@0
   835
    if {[llength $argList] != 5} {
sl@0
   836
	set args [join $argList " "]
sl@0
   837
	puts stderr "Bad .TH macro: .TH $args"
sl@0
   838
    }
sl@0
   839
    incr curID
sl@0
   840
    set name	[lindex $argList 0]		;# Tcl_UpVar
sl@0
   841
    set page	[lindex $argList 1]		;# 3
sl@0
   842
    set curVer	[lindex $argList 2]		;# 7.4
sl@0
   843
    set curPkg	[lindex $argList 3]		;# Tcl
sl@0
   844
    set curSect	[lindex $argList 4]		;# {Tcl Library Procedures}
sl@0
   845
    
sl@0
   846
    regsub -all {\\ } $curSect { } curSect	;# Clean up for [incr\ Tcl]
sl@0
   847
sl@0
   848
    puts $file "#{\\footnote $curID}"		;# Context string
sl@0
   849
    puts $file "\${\\footnote $name}"		;# Topic title
sl@0
   850
    set browse "${curSect}${name}"
sl@0
   851
    regsub -all {[ _-]} $browse {} browse
sl@0
   852
    puts $file "+{\\footnote $browse}"		;# Browse sequence
sl@0
   853
sl@0
   854
    # Suppress duplicates
sl@0
   855
    foreach i $id_keywords($curID) {
sl@0
   856
	set keys($i) 1
sl@0
   857
    }
sl@0
   858
    foreach i [array names keys] {
sl@0
   859
	set i [string trim $i]
sl@0
   860
	if {[string length $i] > 0} {
sl@0
   861
	    puts $file "K{\\footnote $i}"	;# Keyword strings
sl@0
   862
	}
sl@0
   863
    }
sl@0
   864
    unset keys
sl@0
   865
    puts $file "\\pard\\tx3000\\sb100\\sa100\\fs24\\keepn"
sl@0
   866
    font B
sl@0
   867
    text $name
sl@0
   868
    tab
sl@0
   869
    text $curSect
sl@0
   870
    font R
sl@0
   871
    if {[info exists bitmap]} {
sl@0
   872
	# a right justified bitmap
sl@0
   873
	puts $file "\\\{bmrt $bitmap\\\}"
sl@0
   874
    }
sl@0
   875
    puts $file "\\fs20"
sl@0
   876
    set state(breakPending) -1
sl@0
   877
}
sl@0
   878
sl@0
   879
# nextPara --
sl@0
   880
#
sl@0
   881
# Set the indents for a new paragraph, and start a paragraph break
sl@0
   882
#
sl@0
   883
# Arguments:
sl@0
   884
# leftIndent -		The new left margin for body lines.
sl@0
   885
# firstIndent -		The offset from the left margin for the first line.
sl@0
   886
sl@0
   887
proc nextPara {leftIndent {firstIndent 0i}} {
sl@0
   888
    global state
sl@0
   889
    set state(leftIndent) [getTwips $leftIndent]
sl@0
   890
    set state(firstIndent) [getTwips $firstIndent]
sl@0
   891
    set state(paragraphPending) 1
sl@0
   892
}
sl@0
   893
sl@0
   894
sl@0
   895
# newPara --
sl@0
   896
#
sl@0
   897
# This procedure sets the left and hanging state(indent)s for a line.
sl@0
   898
# State(Indent)s are specified in units of inches or centimeters, and are
sl@0
   899
# relative to the current nesting level and left margin.
sl@0
   900
#
sl@0
   901
# Arguments:
sl@0
   902
# leftState(Indent) -		The new left margin for lines after the first.
sl@0
   903
# firstState(Indent) -		The new left margin for the first line of a state(paragraph).
sl@0
   904
sl@0
   905
proc newPara {leftIndent {firstIndent 0i}} {
sl@0
   906
    global state file
sl@0
   907
    if $state(paragraph) {
sl@0
   908
	puts -nonewline $file "\\line\n"
sl@0
   909
    }
sl@0
   910
    if {$leftIndent != ""} {
sl@0
   911
	set state(leftIndent) [expr {$state(leftMargin) \
sl@0
   912
		+ ($state(offset) * $state(nestingLevel)) \
sl@0
   913
		+ [getTwips $leftIndent]}]
sl@0
   914
    }
sl@0
   915
    set state(firstIndent) [getTwips $firstIndent]
sl@0
   916
    set state(paragraphPending) 1
sl@0
   917
}
sl@0
   918
sl@0
   919
sl@0
   920
# getTwips --
sl@0
   921
#
sl@0
   922
# This procedure converts a distance in inches or centimeters into
sl@0
   923
# twips (1/1440 of an inch).
sl@0
   924
#
sl@0
   925
# Arguments:
sl@0
   926
# arg -			A number followed by "i" or "c"
sl@0
   927
sl@0
   928
proc getTwips {arg} {
sl@0
   929
    if {[scan $arg "%f%s" distance units] != 2} {
sl@0
   930
	puts stderr "bad distance \"$arg\""
sl@0
   931
	return 0
sl@0
   932
    }
sl@0
   933
    switch -- $units {
sl@0
   934
	c	{
sl@0
   935
	    set distance [expr {$distance * 567}]
sl@0
   936
	}
sl@0
   937
	i	{
sl@0
   938
	    set distance [expr {$distance * 1440}]
sl@0
   939
	}
sl@0
   940
	default {
sl@0
   941
	    puts stderr "bad units in distance \"$arg\""
sl@0
   942
	    continue
sl@0
   943
	}
sl@0
   944
    }
sl@0
   945
    return $distance
sl@0
   946
}
sl@0
   947
sl@0
   948
# incrNestingLevel --
sl@0
   949
#
sl@0
   950
# This procedure does the work of the .RS macro, which increments
sl@0
   951
# the number of state(indent)ations that affect things like .PP.
sl@0
   952
#
sl@0
   953
# Arguments:
sl@0
   954
# None.
sl@0
   955
sl@0
   956
proc incrNestingLevel {} {
sl@0
   957
    global state
sl@0
   958
sl@0
   959
    incr state(nestingLevel)
sl@0
   960
    set oldp $state(paragraph)
sl@0
   961
    set state(paragraph) 0
sl@0
   962
    newPara 0i
sl@0
   963
    set state(paragraph) $oldp
sl@0
   964
}
sl@0
   965
sl@0
   966
# decrNestingLevel --
sl@0
   967
#
sl@0
   968
# This procedure does the work of the .RE macro, which decrements
sl@0
   969
# the number of indentations that affect things like .PP.
sl@0
   970
#
sl@0
   971
# Arguments:
sl@0
   972
# None.
sl@0
   973
sl@0
   974
proc decrNestingLevel {} {
sl@0
   975
    global state
sl@0
   976
    
sl@0
   977
    if {$state(nestingLevel) == 0} {
sl@0
   978
	puts stderr "Nesting level decremented below 0"
sl@0
   979
    } else {
sl@0
   980
	incr state(nestingLevel) -1
sl@0
   981
    }
sl@0
   982
}
sl@0
   983