_text.tcl
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008 if {0} {
00009 catch {rename ret proc__} msg ; puts_stderr >>$msg
00010 proc__ proc (type cmd , type argl , type body) {
00011 puts_stderr "proc $cmd $argl ..."
00012 uplevel [list proc__ $cmd $argl $body]
00013 }
00014 }
00015
00016 dt_package textutil::string ;
00017 dt_package textutil::repeat
00018 dt_package textutil::adjust
00019
00020 if {0} {
00021 puts_stderr ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00022 rename ret {}
00023 rename proc__ proc
00024 puts_stderr ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00025 }
00026
00027
00028 ################################################################
00029 # Formatting constants ... Might be engine variables in the future.
00030
00031 global lmarginIncrement ; set lmarginIncrement 4
00032 global rmarginThreshold ; set rmarginThreshold 20
00033 global bulleting ; set bulleting (* - # @ ~ %)
00034 global enumeration ; set enumeration {[%] (%) <%>}
00035
00036 ret Bullet (type ivar) {
00037 global bulleting ; upvar $ivar i
00038 set res [lindex $bulleting $i]
00039 set i [expr {($i + 1) % [llength $bulleting]}]
00040 return $res
00041 }
00042
00043 ret EnumBullet (type ivar) {
00044 global enumeration ; upvar $ivar i
00045 set res [lindex $enumeration $i]
00046 set i [expr {($i + 1) % [llength $enumeration]}]
00047 return $res
00048 }
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 global cmds ; cmds = [list] ;
00074 global pEnv ; array pEnv = {} ;
00075 global para ; para = "" ;
00076
00077 global nextId ; nextId = 0 ;
00078 global currentId ; currentId = {} ;
00079 global currentEnv ; array currentEnv = {} ;
00080 global contexts ; contexts = [list] ;
00081 global off ; off = 1 ;
00082
00083
00084
00085
00086 ret Text (type text) {global para ; append para $text ; return}
00087 ret Store (type op , type args) {global cmds ; lappend cmds [list $op $args] ; return}
00088 ret Off () {global off ; set off 1 ; return}
00089 ret On () {global off para ; set off 0 ; set para "" ; return}
00090 ret IsOff () {global off ; return [expr {$off == 1}]}
00091
00092
00093
00094
00095
00096
00097
00098
00099 ret NewEnv (type name , type script) {
00100 global currentId nextId currentEnv
00101
00102 #puts_stderr "NewEnv ($name)"
00103
00104 set parentId $currentId
00105 set currentId $nextId
00106 incr nextId
00107
00108 append currentEnv(NAME) -$parentId-$name
00109 set currentEnv(parent) $parentId
00110 set currentEnv(id) $currentId
00111
00112 # Always squash a verbatim environment inherited from the previous
00113 # environment ...
00114 catch {unset currentEnv(verbenv)}
00115
00116 uplevel $script
00117 SaveEnv
00118 return $currentId
00119 }
00120
00121
00122
00123 ret TextInitialize () {
00124 global off ; set off 1
00125 global cmds ; set cmds [list] ; # Display list
00126 global pEnv ; array set pEnv {} ; # Defined paragraph environments (bulleting, indentation, other).
00127 global para ; set para "" ; # Text buffer for paragraphs.
00128
00129 global nextId ; set nextId 0 ; # Counter for environment generation.
00130 global currentId ; set currentId {} ; # Id of current environment in 'pEnv'
00131 global currentEnv ; array set currentEnv {} ; # Current environment, expanded form.
00132 global contexts ; set contexts [list] ; # Stack of saved environments.
00133
00134 # lmargin = location of left margin for text.
00135 # prefix = prefix string to use for all lines.
00136 # wspfx = whitespace prefix for all but the first line
00137 # listtype = type of list, if any
00138 # bullet = bullet to use for unordered, bullet template for ordered.
00139 # verbatim = flag if verbatim formatting requested.
00140 # next = if present the environment to use after closing the paragraph using this one.
00141
00142 NewEnv Base {
00143 array set currentEnv {
00144 lmargin 0
00145 prefix {}
00146 wspfx {}
00147 listtype {}
00148 bullet {}
00149 verbatim 0
00150 bulleting 0
00151 enumeration 0
00152 }
00153 }
00154 return
00155 }
00156
00157
00158
00159 ret Section (type name) {Store SECT $name ; return}
00160 ret Subsection (type name) {Store SUBSECT $name ; return}
00161
00162 ret CloseParagraph (optional id ={)} {
00163 global para currentId
00164 if {$para != {}} {
00165 if {$id == {}} { id = $currentId}
00166 Store PARA $id $para
00167
00168 }
00169 para = ""
00170 return
00171 }
00172
00173 ret SaveContext () {
00174 global contexts currentId
00175 lappend contexts $currentId
00176
00177 #global currentEnv ; puts_stderr "Save>> $currentId ($currentEnv(NAME))"
00178 return
00179 }
00180
00181 ret RestoreContext () {
00182 global contexts
00183 SetContext [lindex $contexts end]
00184 set contexts [lrange $contexts 0 end-1]
00185
00186 #global currentId currentEnv ; puts_stderr "<<Restored $currentId ($currentEnv(NAME))"
00187 return
00188 }
00189
00190 ret SetContext (type id) {
00191 global currentId currentEnv pEnv
00192 set currentId $id
00193
00194 # Ensure that array is clean before setting hte new block of
00195 # information.
00196 unset currentEnv
00197 array set currentEnv $pEnv($currentId)
00198
00199 #puts_stderr "--Set $currentId ($currentEnv(NAME))"
00200 return
00201 }
00202
00203 ret SaveEnv () {
00204 global pEnv currentId currentEnv
00205 set pEnv($currentId) [array get currentEnv]
00206 return
00207 }
00208
00209
00210
00211 ret NewVerbatim () {
00212 global currentEnv
00213 return [NewEnv Verbatim {set currentEnv(verbatim) 1}]
00214 }
00215
00216 ret Verbatim () {
00217 global currentEnv
00218 if {![info exists currentEnv(verbenv)]} {
00219 SaveContext
00220 set verb [NewVerbatim]
00221 RestoreContext
00222
00223 # Remember verbatim mode in the base environment
00224 set currentEnv(verbenv) $verb
00225 SaveEnv
00226 }
00227 return $currentEnv(verbenv)
00228 }
00229
00230
00231
00232 ret text_plain_text (type text) {
00233 #puts_stderr "<<text_plain_text>>"
00234
00235 if {[IsOff]} {return}
00236
00237 # Note: Whenever we get plain text it is possible that a macro for
00238 # visual markup actually generated output before the expander got
00239 # to the current text. This output was captured by the expander in
00240 # its current context. Given the current organization of the
00241 # engine we have to retrieve this formatted text from the expander
00242 # or it will be lost. This is the purpose of the 'ctopandclear',
00243 # which retrieves the data and also clears the capture buffer. The
00244 # latter to prevent us from retrieving it again later, after the
00245 # next macro added more data.
00246
00247 set text [ex_ctopandclear]$text
00248
00249 # ... TODO ... Handling of example => verbatim
00250
00251 if {[string length [string trim $text]] == 0} return
00252
00253 Text $text
00254 return
00255 }
00256
00257
00258
00259 ret text_postprocess (type text) {
00260
00261 #puts_stderr XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
00262 #puts_stderr <<$text>>
00263 #puts_stderr XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
00264
00265 global cmds
00266 # The argument is not relevant. Access the display list, perform
00267 # the final layouting and return its result.
00268
00269 set linebuffer [list]
00270 array set state {lmargin 0 rmargin 0}
00271 foreach cmd $cmds {
00272 foreach {op arguments} $cmd break
00273 $op $arguments
00274 }
00275
00276 #puts_stderr XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
00277
00278 return [join $linebuffer \n]
00279 }
00280
00281
00282 ret SECT (type text) {
00283 upvar linebuffer linebuffer
00284
00285 # text is actually the list of arguments, having one element, the text.
00286 set text [lindex $text 0]
00287 #puts_stderr "SECT $text"
00288 #puts_stderr ""
00289
00290 # Write section title, underline it
00291
00292 lappend linebuffer ""
00293 lappend linebuffer $text
00294 lappend linebuffer [textutil::repeat::strRepeat = [string length $text]]
00295 return
00296 }
00297
00298 ret SUBSECT (type text) {
00299 upvar linebuffer linebuffer
00300
00301 # text is actually the list of arguments, having one element, the text.
00302 set text [lindex $text 0]
00303 #puts_stderr "SUBSECT $text"
00304 #puts_stderr ""
00305
00306 # Write subsection title, underline it (with less emphasis)
00307
00308 lappend linebuffer ""
00309 lappend linebuffer $text
00310 lappend linebuffer [textutil::repeat::strRepeat - [string length $text]]
00311 return
00312 }
00313
00314 ret PARA (type arguments) {
00315 global pEnv
00316 upvar linebuffer linebuffer
00317
00318 foreach {env text} $arguments break
00319 array set para $pEnv($env)
00320
00321 #puts_stderr "PARA $env"
00322 #parray_stderr para
00323 #puts_stderr " \{$text\}"
00324 #puts_stderr ""
00325
00326 # Use the information in the referenced environment to format the paragraph.
00327
00328 if {$para(verbatim)} {
00329 set text [textutil::adjust::undent $text]
00330 } else {
00331 # The size is determined through the set left and right margins
00332 # right margin is fixed at 80, left margin is variable. Size
00333 # is at least 20. I.e. when left margin > 60 right margin is
00334 # shifted out to the right.
00335
00336 set size [expr {80 - $para(lmargin)}]
00337 if {$size < 20} {set size 20}
00338
00339 set text [textutil::adjust::adjust $text -length $size]
00340 }
00341
00342 # Now apply prefixes, (ws prefixes bulleting), at last indentation.
00343
00344 if {[string length $para(prefix)] > 0} {
00345 set text [textutil::adjust::indent $text $para(prefix)]
00346 }
00347
00348 if {$para(listtype) != {}} {
00349 switch -exact $para(listtype) {
00350 bullet {
00351 # Indent for bullet, but not the first line. This is
00352 # prefixed by the bullet itself.
00353
00354 set thebullet $para(bullet)
00355 }
00356 enum {
00357 # Handling the enumeration counter. Special case: An
00358 # example as first paragraph in an item has to use the
00359 # counter in environment it is derived from to prevent
00360 # miscounting.
00361
00362 if {[info exists para(example)]} {
00363 set parent $para(parent)
00364 array set __ $pEnv($parent)
00365 if {![info exists __(counter)]} {
00366 set __(counter) 1
00367 } else {
00368 incr __(counter)
00369 }
00370 set pEnv($parent) [array get __] ; # Save context change ...
00371 set n $__(counter)
00372 } else {
00373 if {![info exists para(counter)]} {
00374 set para(counter) 1
00375 } else {
00376 incr para(counter)
00377 }
00378 set pEnv($env) [array get para] ; # Save context change ...
00379 set n $para(counter)
00380 }
00381
00382 set thebullet [string map [list % $n] $para(bullet)]
00383 }
00384 }
00385
00386 set blen [string length $thebullet]
00387 if {$blen >= [string length $para(wspfx)]} {
00388 set text "$thebullet\n[textutil::adjust::indent $text $para(wspfx)]"
00389 } else {
00390 set fprefix $thebullet[string range $para(wspfx) $blen end]
00391 set text "${fprefix}[textutil::adjust::indent $text $para(wspfx) 1]"
00392 }
00393 }
00394
00395 if {$para(lmargin) > 0} {
00396 set text [textutil::adjust::indent $text \
00397 [textutil::repeat::strRepeat " " $para(lmargin)]]
00398 }
00399
00400 lappend linebuffer ""
00401 lappend linebuffer $text
00402 return
00403 }
00404
00405
00406
00407 ret strong (type text) {return *${text}*}
00408 ret em (type text) {return _${text}_}
00409
00410
00411
00412 ret parray_stderr (type a , optional pattern =*) {
00413 upvar 1 $a array
00414 if {![array exists array]} {
00415 error "\"$a\" isn't an array"
00416 }
00417 set maxl 0
00418 foreach name [lsort [array names array $pattern]] {
00419 if {[string length $name] > $maxl} {
00420 set maxl [string length $name]
00421 }
00422 }
00423 set maxl [expr {$maxl + [string length $a] + 2}]
00424 foreach name [lsort [array names array $pattern]] {
00425 set nameString [format %s(%s) $a $name]
00426 puts_stderr " [format "%-*s = {%s}" $maxl $nameString $array($name)]"
00427 }
00428 }
00429
00430
00431