#unprefixed colours are (close to) the ansi-specified colour names (lower-cased and whitespace collapsed, with capitalisation of 1st letter given fg/bg meaning here)
variable SGR_colour_map {
black 30 red 31 green 32 yellow 33 blue 34 purple 35 cyan 36 white 37
Black 40 Red 41 Green 42 Yellow 43 Blue 44 Purple 45 Cyan 46 White 47
#specified in decimal - but we should also accept hex format directly in a+ function e.g #00FFFF for aqua
variable WEB_colour_map
#use the totitle format as the canonical lookup key
#don't use leading zeros - keep compatible with earlier tcl and avoid octal issue
# -- --- ---
#css 1-2.0 HTML 3.2-4 Basic colours eg web-silver for fg Web-silver for bg
#
dict set WEB_colour_map white 255-255-255 ;# #FFFFFF
dict set WEB_colour_map silver 192-192-192 ;# #C0C0C0
dict set WEB_colour_map gray 128-128-128 ;# #808080
dict set WEB_colour_map black 0-0-0 ;# #000000
dict set WEB_colour_map red 255-0-0 ;# #FF0000
dict set WEB_colour_map maroon 128-0-0 ;# #800000
dict set WEB_colour_map yellow 255-255-0 ;# #FFFF00
dict set WEB_colour_map olive 128-128-0 ;# #808000
dict set WEB_colour_map lime 0-255-0 ;# #00FF00
dict set WEB_colour_map green 0-128-0 ;# #008000
dict set WEB_colour_map aqua 0-255-255 ;# #00FFFF
dict set WEB_colour_map teal 0-128-128 ;# #008080
dict set WEB_colour_map blue 0-0-255 ;# #0000FF
dict set WEB_colour_map navy 0-0-128 ;# #000080
dict set WEB_colour_map fuchsia 255-0-255 ;# #FF00FF
dict set WEB_colour_map purple 128-0-128 ;# #800080
# -- --- ---
#Pink colours
dict set WEB_colour_map mediumvioletred 199-21-133 ;# #C71585
dict set WEB_colour_map deeppink 255-20-147 ;# #FF1493
dict set WEB_colour_map palevioletred 219-112-147 ;# #DB7093
dict set WEB_colour_map hotpink 255-105-180 ;# #FF69B4
dict set WEB_colour_map lightpink 255-182-193 ;# #FFB6C1
dict set WEB_colour_map pink 255-192-203 ;# #FFCOCB
# -- --- ---
#Red colours
dict set WEB_colour_map darkred 139-0-0 ;# #8B0000
#red - as above
dict set WEB_colour_map firebrick 178-34-34 ;# #B22222
dict set WEB_colour_map crimson 220-20-60 ;# #DC143C
dict set WEB_colour_map indianred 205-92-92 ;# #CD5C5C
dict set WEB_colour_map lightcoral 240-128-128 ;# #F08080
dict set WEB_colour_map salmon 250-128-114 ;# #FA8072
dict set WEB_colour_map darksalmon 233-150-122 ;# #E9967A
dict set WEB_colour_map lightsalmon 255-160-122 ;# #FFA07A
# -- --- ---
#Orange colours
dict set WEB_colour_map orangered 255-69-0 ;# #FF4500
dict set WEB_colour_map tomato 255-99-71 ;# #FF6347
dict set WEB_colour_map darkorange 255-140-0 ;# #FF8C00
dict set WEB_colour_map coral 255-127-80 ;# #FF7F50
dict set WEB_colour_map orange 255-165-0 ;# #FFA500
# -- --- ---
#Yellow colours
dict set WEB_colour_map darkkhaki 189-183-107 ;# #BDB76B
dict set WEB_colour_map gold 255-215-0 ;# #FFD700
dict set WEB_colour_map khaki 240-230-140 ;# #F0E68C
dict set WEB_colour_map peachpuff 255-218-185 ;# #FFDAB9
#yellow - as above
dict set WEB_colour_map palegoldenrod 238-232-170 ;# #EEE8AA
dict set WEB_colour_map moccasin 255-228-181 ;# #FFE4B5
dict set WEB_colour_map papayawhip 255-239-213 ;# #FFEFD5
dict set WEB_colour_map lightgoldenrodyeallow 250-250-210 ;# #FAFAD2
dict set WEB_colour_map lemonchiffon 255-250-205 ;# #FFFACD
dict set WEB_colour_map lightyellow 255-255-224 ;# #FFFFE0
# -- --- ---
#Brown colours
#maroon as above
dict set WEB_colour_map brown 165-42-42 ;# #A52A2A
dict set WEB_colour_map saddlebrown 139-69-19 ;# #8B4513
dict set WEB_colour_map sienna 160-82-45 ;# #A0522D
dict set WEB_colour_map chocolate 210-105-30 ;# #D2691E
dict set WEB_colour_map darkgoldenrod 184-134-11 ;# #B8860B
dict set WEB_colour_map peru 205-133-63 ;# #CD853F
dict set WEB_colour_map rosybrown 188-143-143 ;# #BC8F8F
dict set WEB_colour_map goldenrod 218-165-32 ;# #DAA520
dict set WEB_colour_map sandybrown 244-164-96 ;# #F4A460
dict set WEB_colour_map tan 210-180-140 ;# #D2B48C
dict set WEB_colour_map burlywood 222-184-135 ;# #DEB887
dict set WEB_colour_map wheat 245-222-179 ;# #F5DEB3
dict set WEB_colour_map navajowhite 255-222-173 ;# #FFDEAD
dict set WEB_colour_map bisque 255-228-196 ;# #FFEfC4
dict set WEB_colour_map blanchedalmond 255-228-196 ;# #FFEfC4
dict set WEB_colour_map cornsilk 255-248-220 ;# #FFF8DC
# -- --- ---
#Purple, violet, and magenta colours
dict set WEB_colour_map indigo 75-0-130 ;# #4B0082
#purple as above
dict set WEB_colour_map darkmagenta 139-0-139 ;# #8B008B
dict set WEB_colour_map darkviolet 148-0-211 ;# #9400D3
dict set WEB_colour_map darkslateblue 72-61-139 ;# #9400D3
dict set WEB_colour_map blueviolet 138-43-226 ;# #8A2BE2
dict set WEB_colour_map darkorchid 153-50-204 ;# #9932CC
#fuchsia as above
dict set WEB_colour_map magenta 255-0-255 ;# #FF00FF - same as fuchsia
dict set WEB_colour_map slateblue 106-90-205 ;# #6A5ACD
dict set WEB_colour_map mediumslateblue 123-104-238 ;# #7B68EE
dict set WEB_colour_map mediumorchid 186-85-211 ;# #BA5503
dict set WEB_colour_map mediumpurple 147-112-219 ;# #9370DB
dict set WEB_colour_map orchid 218-112-214 ;# #DA70D6
dict set WEB_colour_map violet 238-130-238 ;# #EE82EE
dict set WEB_colour_map plum 221-160-221 ;# #DDA0DD
dict set WEB_colour_map thistle 216-191-216 ;# #D88FD8
dict set WEB_colour_map lavender 230-230-150 ;# #E6E6FA
# -- --- ---
#Blue colours
dict set WEB_colour_map midnightblue 25-25-112 ;# #191970
#navy as above
dict set WEB_colour_map darkblue 0-0-139 ;# #00008B
dict set WEB_colour_map mediumblue 0-0-205 ;# #0000CD
#blue as above
dict set WEB_colour_map royalblue 65-105-225 ;# #4169E1
dict set WEB_colour_map steelblue 70-130-180 ;# #4682B4
dict set WEB_colour_map dodgerblue 30-144-255 ;# #1E90FF
dict set WEB_colour_map deepskyblue 0-191-255 ;# #00BFFF
dict set WEB_colour_map cornflowerblue 100-149-237 ;# #6495ED
dict set WEB_colour_map skyblue 135-206-235 ;# #87CEEB
dict set WEB_colour_map lightskyblue 135-206-250 ;# #87CEFA
dict set WEB_colour_map lightsteelblue 176-196-222 ;# #B0C4DE
dict set WEB_colour_map lightblue 173-216-230 ;# #ADD8E6
dict set WEB_colour_map powderblue 176-224-230 ;# #B0E0E6
# -- --- ---
#Cyan colours
#teal as above
dict set WEB_colour_map darkcyan 0-139-139 ;# #008B8B
dict set WEB_colour_map lightseagreen 32-178-170 ;# #20B2AA
dict set WEB_colour_map cadetblue 95-158-160 ;# #5F9EA0
dict set WEB_colour_map darkturquoise 0-206-209 ;# #00CED1
dict set WEB_colour_map mediumturquoise 72-209-204 ;# #48D1CC
dict set WEB_colour_map turquoise 64-224-208 ;# #40E0D0
#aqua as above
dict set WEB_colour_map cyan 0-255-255 ;# #00FFFF - same as aqua
dict set WEB_colour_map aquamarine 127-255-212 ;# #7FFFD4
dict set WEB_colour_map paleturquoise 175-238-238 ;# #AFEEEE
dict set WEB_colour_map lightcyan 224-255-255 ;# #E0FFFF
# -- --- ---
#Green colours
dict set WEB_colour_map darkgreen 0-100-0 ;# #006400
#green as above
dict set WEB_colour_map darkolivegreen 85-107-47 ;# #55682F
dict set WEB_colour_map forestgreen 34-139-34 ;# #228B22
dict set WEB_colour_map seagrean 46-139-87 ;# #2E8B57
#olive as above
dict set WEB_colour_map olivedrab 107-142-35 ;# #6B8E23
dict set WEB_colour_map mediumseagreen 60-179-113 ;# #3CB371
dict set WEB_colour_map limegreen 50-205-50 ;# #32CD32
#lime as above
dict set WEB_colour_map springgreen 0-255-127 ;# #00FF7F
dict set WEB_colour_map mediumspringgreen 0-250-154 ;# #00FA9A
dict set WEB_colour_map darkseagreen 143-188-143 ;# #8FBC8F
dict set WEB_colour_map mediumaquamarine 102-205-170 ;# #66CDAA
dict set WEB_colour_map yellowgreen 154-205-50 ;# #9ACD32
dict set WEB_colour_map lawngreen 124-252-0 ;# #7CFC00
dict set WEB_colour_map chartreuse 127-255-0 ;# #7FFF00
dict set WEB_colour_map lightgreen 144-238-144 ;# #90EE90
dict set WEB_colour_map greenyellow 173-255-47 ;# #ADFF2F
dict set WEB_colour_map palegreen 152-251-152 ;# #98FB98
# -- --- ---
#White colours
dict set WEB_colour_map mistyrose 255-228-225 ;# #FFE4E1
dict set WEB_colour_map antiquewhite 250-235-215 ;# #FAEBD7
dict set WEB_colour_map linen 250-240-230 ;# #FAF0E6
dict set WEB_colour_map beige 245-245-220 ;# #F5F5DC
dict set WEB_colour_map whitesmoke 245-245-245 ;# #F5F5F5
dict set WEB_colour_map lavenderblush 255-240-245 ;# #FFF0F5
dict set WEB_colour_map oldlace 253-245-230 ;# #FDF5E6
dict set WEB_colour_map aliceblue 240-248-255 ;# #F0F8FF
dict set WEB_colour_map seashell 255-245-238 ;# #FFF5EE
dict set WEB_colour_map ghostwhite 248-248-255 ;# #F8F8FF
dict set WEB_colour_map honeydew 240-255-240 ;# #F0FFF0
dict set WEB_colour_map floralwhite 255-250-240 ;# #FFFAF0
dict set WEB_colour_map azure 240-255-255 ;# #F0FFFF
dict set WEB_colour_map mintcream 245-255-250 ;# #F5FFFA
dict set WEB_colour_map snow 255-250-250 ;# #FFFAFA
dict set WEB_colour_map ivory 255-255-240 ;# #FFFFF0
#white as above
# -- --- ---
#Gray and black colours
#black as above
dict set WEB_colour_map darkslategray 47-79-79 ;# #2F4F4F
dict set WEB_colour_map dimgray 105-105-105 ;# #696969
dict set WEB_colour_map slategray 112-128-144 ;# #708090
#gray as above
dict set WEB_colour_map lightslategray 119-136-153 ;# #778899
dict set WEB_colour_map darkgray 169-169-169 ;# #A9A9A9
dict set WEB_colour_map silver 192-192-192 ;# #C0C0C0
dict set WEB_colour_map lightgray 211-211-211 ;# #D3D3D3
dict set WEB_colour_map gainsboro 220-220-220 ;# #DCDCDC
#we should be able to use WEB_colour_map as a base and override only the conflicts for X11 colours ? Review - check if this is true
variable X11_colour_map
set X11_colour_map $WEB_colour_map
dict set X11_colour_map gray 190-190-190 ;# #BEBEBE
dict set X11_colour_map green 0-255-0 ;# #00FF00
dict set X11_colour_map maroon 176-48-96 ;# #B03060
dict set X11_colour_map purple 160-32-240 ;# #A020F0
#Xterm colour names (256 colours)
#lists on web have duplicate names
#these have been renamed here in a systematic way:
#They are suffixed with a dash and a letter e.g second deepskyblue4 -> deepskyblue4-b, third deepskyblue4 -> deepskyblue4-c
#presumably the xterm colour names are not widely used or are used for reverse lookup from rgb to get an approximate name in the case of dupes?
#Review!
#keep duplicate names in the list and map them when building the dict.
#This is an in depth analysis of the xterm colour set which gives names(*) to all of the 256 colours and describes possible indexing by Hue,Luminance,Saturation
#https://www.wowsignal.io/articles/xterm256
#*The names are wildly-imaginative, often unintuitively so, and multiple (5?) given for each colour - so they are unlikely to be of practical use or any sort of standard.
#e.g who is to know that 'Rabbit Paws', 'Forbidden Thrill' and 'Tarsier' refer to a particular shade of pinky-red? (code 95)
#Perhaps it's an indication that colour naming once we get to 256 colours or more is a fool's errand anyway.
#The xterm names are boringly unimaginative - and also have some oddities such as:
# DarkSlateGray1 which looks much more like cyan..
# The greyxx names are spelt with an e - but the darkslategrayX variants use an a. Perhaps that's because they are more cyan than grey and the a is a hint?
# there is no gold or gold2 - but there is gold1 and gold3
#but in general the names bear some resemblance to the colours and are at least somewhat intuitive.
set xterm_names [list\
black\
maroon\
green\
olive\
navy\
purple\
teal\
silver\
grey\
red\
lime\
yellow\
blue\
fuchsia\
aqua\
white\
grey0\
navyblue\
darkblue\
blue3\
blue3\
blue1\
darkgreen\
deepskyblue4\
deepskyblue4\
deepskyblue4\
dodgerblue3\
dodgerblue2\
green4\
springgreen4\
turquise4\
deepskyblue3\
deepskyblue3\
dodgerblue1\
green3\
springgreen3\
darkcyan\
lightseagreen\
deepskyblue2\
deepskyblue1\
green3\
springgreen3\
springgreen2\
cyan3\
darkturquoise\
turquoise2\
green1\
springgreen2\
springgreen1\
mediumspringgreen\
cyan2\
cyan1\
darkred\
deeppink4\
purple4\
purple4\
purple3\
blueviolet\
orange4\
grey37\
mediumpurple4\
slateblue3\
slateblue3\
royalblue1\
chartreuse4\
darkseagreen4\
paleturquoise4\
steelblue\
steelblue3\
cornflowerblue\
chartreuse3\
darkseagreen4\
cadetblue\
cadetblue\
skyblue3\
steelblue1\
chartreuse3\
palegreen3\
seagreen3\
aquamarine3\
mediumturquoise\
steelblue1\
chartreuse2\
seagreen2\
seagreen1\
seagreen1\
aquamarine1\
darkslategray2\
darkred\
deeppink4\
darkmagenta\
darkmagenta\
darkviolet\
purple\
orange4\
lightpink4\
plum4\
mediumpurple3\
mediumpurple3\
slateblue1\
yellow4\
wheat4\
grey53\
lightslategrey\
mediumpurple\
lightslateblue\
yellow4\
darkolivegreen3\
darkseagreen\
lightskyblue3\
lightskyblue3\
skyblue2\
chartreuse2\
darkolivegreen3\
palegreen3\
darkseagreen3\
darkslategray3\
skyblue1\
chartreuse1\
lightgreen\
lightgreen\
palegreen1\
aquamarine1\
darkslategray1\
red3\
deeppink4\
mediumvioletred\
magenta3\
darkviolet\
purple\
darkorange3\
indianred\
hotpink3\
mediumorchid3\
mediumorchid\
mediumpurple2\
darkgoldenrod\
lightsalmon3\
rosybrown\
grey63\
mediumpurple2\
mediumpurple1\
gold3\
darkkhaki\
navajowhite\
grey69\
lightsteelblue3\
lightsteelblue\
yellow3\
darkolivegreen3\
darkseagreen3\
darkseagreen2\
lightcyan3\
lightskyblue1\
greenyellow\
darkolivegreen2\
palegreen1\
darkseagreen2\
darkseagreen1\
paleturquoise1\
red3\
deppink3\
deeppink3\
magenta3\
magenta3\
magenta2\
darkorange3\
indianred\
hotpink3\
hotpink2\
orchid\
mediumorchid1\
orange3\
lightsalmon3\
lightpink3\
pink3\
plum3\
violet\
gold3\
lightgoldenrod3\
tan\
mistyrose3\
thistle3\
plum2\
yellow3\
khaki3\
lightgoldenrod2\
lightyellow3\
grey84\
lightsteelblue1\
yellow2\
darkolivegreen1\
darkolivegreen1\
darkseagreen1\
honeydew2\
lightcyan1\
red1\
deeppink2\
deeppink1\
deeppink1\
magenta2\
magenta1\
orangered1\
indianred1\
indianred1\
hotpink\
hotpink\
mediumorchid1\
darkorange\
salmon1\
lightcoral\
palevioletred1\
orchid2\
orchid1\
orange1\
sandybrown\
lightsalmon1\
lightpink1\
pink1\
plum1\
gold1\
lightgoldenrod2\
lightgoldenrod2\
navajowhite1\
mistyrose1\
thistle1\
yellow1\
lightgoldenrod1\
khaki1\
wheat1\
cornsilk1\
grey100\
grey3\
grey7\
grey11\
grey11\
grey15\
grey19\
grey23\
grey27\
grey30\
grey35\
grey39\
grey42\
grey46\
grey50\
grey54\
grey58\
grey62\
grey66\
grey70\
grey74\
grey78\
grey82\
grey85\
grey89\
grey93\
]
variable TERM_colour_map
set TERM_colour_map [dict create]
set cidx 0
foreach cname $xterm_names {
if {![dict exists $TERM_colour_map $cname]} {
dict set TERM_colour_map $cname $cidx
} else {
set did_rename 0
#start suffixes at '-b'. The base name could be considered the '-a' version - but we don't create it.
foreach {suffix} {b c} {
if {![dict exists $TERM_colour_map $cname-$suffix]} {
dict set TERM_colour_map $cname-$suffix $cidx
set did_rename 1
break
}
}
if {!$did_rename} {
error "Not enough suffixes for duplicate names in xterm colour list. Add more suffixes or review list"
}
}
incr cidx
}
#colour_hex2dec
#conversion of hex to format directly pluggable to ansi rgb format (colon separated e.g for foreground we need "38;2;$r;$g;$b" so we return $r;$g;$b)
#we want to support arbitrary rgb values specified in hex - so a table of 16M+ is probably not a great idea
#hex zero-padded - canonically upper case but mixed or lower accepted
set spacemap [list hl "\uFFFF" vl "\uFFFF" tlc "\uFFFF" blc "\uFFFF" trc "\uFFFF " brc "\uFFFF"] ;# a debug test
set header_frame [textblock::frame -width 0 -type [dict get $ftypes header]\
-ansibase $ansibase_header \
-boxlimits $hlims -boxmap $spacemap $hcell_blank\
]
append part_header $header_frame\n
} else {
#test version
set hw1 [dict get $o_columnstates $cidx maxwidthheaderseen] ;#headers may be masked by spans, or empty - width may depend more on spans than headers in current column
set hw2 [textblock::width $part_header] ;#widest so far
set hw3 [expr {max($hw1,$hw2)}]
set bw [dict get $o_columnstates $cidx maxwidthbodyseen]
set padwidth [expr {max($hw3,$bw)}]
if {[dict exists $column_width_cache $cidx]} {
set hwidth [dict get $column_width_cache $cidx headerwidth]
set padwidth [expr {max($padwidth,$hwidth)}]
}
#test hack - wider helps stop the breaks - but leaves junk spaces and ansiresets beyond the rhs border of table
#print function overflow 0 fixes?
set padwidth 20
#set bline [string repeat \uFFFF $colwidth]
set bline [string repeat \uFFFF $padwidth]
set h_lines [lrepeat $rowh $bline]
set hcell_blank [::join $h_lines \n]
set spacemap [list hl "\uFFFF" vll "\uFFFF" vlr "\uFFFF" tlc "\uFFFF" blc "\uFFFF" trc "\uFFFF " brc "\uFFFF"] ;# a debug test
set header_frame [textblock::frame -width [expr {$padwidth+2}] -type [dict get $ftypes header]\
-ansibase $ansibase_header \
-boxlimits $hlims -boxmap $spacemap $hcell_blank\
]
append part_header $header_frame\n
}
}
incr h
}
@ -1543,30 +1583,56 @@ namespace eval textblock {
set opt_col_ansibase [dict get $o_columndefs $colidx -ansibase] ;#ordinary merge of codes already done in configure_column
set body_ansibase [dict get $o_opts_table -ansibase_body]
set ansibase $body_ansibase$opt_col_ansibase ;#allow col to override body
#set ansibase [punk::ansi::codetype::sgr_merge_singles [list $body_ansibase $opt_col_ansibase]] ;#allow col to override body
set ansibase $body_ansibase$opt_col_ansibase
set body_ansiborder [dict get $o_opts_table -ansiborder_body]
if {[dict get $o_opts_table -frametype] eq "block"} {
#block is the only style where bg colour can fill the frame content area exactly if the L-shaped border elements are styled
#we need to only accept background ansi codes from the columndef ansibase for this
set col_bg [punk::ansi::codetype::sgr_merge [list $opt_col_ansibase] -filter_fg 1] ;#special merge for block borders - don't override fg colours
set col_bg [punk::ansi::codetype::sgr_merge_singles [list $opt_col_ansibase] -filter_fg 1] ;#special merge for block borders - don't override fg colours
set border_ansi $body_ansibase$body_ansiborder$col_bg
} else {
set border_ansi $body_ansibase$body_ansiborder
}
set r 0
foreach c $cells {
set row_ansibase [dict get $o_rowdefs $r -ansibase]
#todo - joinleft,joinright,joindown based on opts in args
#if padchar width (screen width) > 1 - length calculations will not be correct
#we will allow tokens longer than 1 - as the caller may want to post-process on the token whilst preserving previous leading/trailing spaces, e.g with a string map
#The caller may also use ansi within the padchar - although it's unlikely to be efficient.
# -- --- --- --- --- --- --- --- --- ---
set known_whiches [list l left r right c center centre]
set which [string tolower [dict get $opts -which]]
if {$which in [list centre center]} {set which "c"}
if {$which in [list left]} {set which "l"}
if {$which in [list right]} {set which "r"}
if {$which ni $known_whiches} {
error "textblock::pad unrecognised value for -which option. Known values $known_whiches"
set opt_which [string tolower [dict get $opts -which]]
switch -- $opt_which {
center - centre - c {
set which c
}
left - l {
set which l
}
right - r {
set which r
}
default {
error "textblock::pad unrecognised value for -which option. Known values $known_whiches"
}
}
# -- --- --- --- --- --- --- --- --- ---
set width [dict get $opts -width]
set opt_width [dict get $opts -width]
switch -- $opt_width {
"" - auto {
set width auto
}
default {
if {![string is integer -strict $opt_width] || $opt_width < 0} {
error "textblock::pad -width must be an integer >=0"
error "_insert_before_text_or_last_ansi ansisplits list is not a valid resultlist from an ansi split - must be odd number of elements pt,ansi,pt,ansi...pt"
}
set out [list]
set i 0
set i_last_code [expr {[llength $ansisplits]-3}] ;#would normally be -2 - but our i is jumping to each pt - not every element
foreach {pt code} $ansisplits {
if {$pt ne ""} {
return [lappend out $str {*}[lrange $ansisplits $i end]]
}
if {$i == $i_last_code} {
return [lappend out $str {*}[lrange $ansisplits $i end]]
}
#code being empty can only occur when we have reached last pt
#unprefixed colours are (close to) the ansi-specified colour names (lower-cased and whitespace collapsed, with capitalisation of 1st letter given fg/bg meaning here)
variable SGR_colour_map {
black 30 red 31 green 32 yellow 33 blue 34 purple 35 cyan 36 white 37
Black 40 Red 41 Green 42 Yellow 43 Blue 44 Purple 45 Cyan 46 White 47
#specified in decimal - but we should also accept hex format directly in a+ function e.g #00FFFF for aqua
variable WEB_colour_map
#use the totitle format as the canonical lookup key
#don't use leading zeros - keep compatible with earlier tcl and avoid octal issue
# -- --- ---
#css 1-2.0 HTML 3.2-4 Basic colours eg web-silver for fg Web-silver for bg
#
dict set WEB_colour_map white 255-255-255 ;# #FFFFFF
dict set WEB_colour_map silver 192-192-192 ;# #C0C0C0
dict set WEB_colour_map gray 128-128-128 ;# #808080
dict set WEB_colour_map black 0-0-0 ;# #000000
dict set WEB_colour_map red 255-0-0 ;# #FF0000
dict set WEB_colour_map maroon 128-0-0 ;# #800000
dict set WEB_colour_map yellow 255-255-0 ;# #FFFF00
dict set WEB_colour_map olive 128-128-0 ;# #808000
dict set WEB_colour_map lime 0-255-0 ;# #00FF00
dict set WEB_colour_map green 0-128-0 ;# #008000
dict set WEB_colour_map aqua 0-255-255 ;# #00FFFF
dict set WEB_colour_map teal 0-128-128 ;# #008080
dict set WEB_colour_map blue 0-0-255 ;# #0000FF
dict set WEB_colour_map navy 0-0-128 ;# #000080
dict set WEB_colour_map fuchsia 255-0-255 ;# #FF00FF
dict set WEB_colour_map purple 128-0-128 ;# #800080
# -- --- ---
#Pink colours
dict set WEB_colour_map mediumvioletred 199-21-133 ;# #C71585
dict set WEB_colour_map deeppink 255-20-147 ;# #FF1493
dict set WEB_colour_map palevioletred 219-112-147 ;# #DB7093
dict set WEB_colour_map hotpink 255-105-180 ;# #FF69B4
dict set WEB_colour_map lightpink 255-182-193 ;# #FFB6C1
dict set WEB_colour_map pink 255-192-203 ;# #FFCOCB
# -- --- ---
#Red colours
dict set WEB_colour_map darkred 139-0-0 ;# #8B0000
#red - as above
dict set WEB_colour_map firebrick 178-34-34 ;# #B22222
dict set WEB_colour_map crimson 220-20-60 ;# #DC143C
dict set WEB_colour_map indianred 205-92-92 ;# #CD5C5C
dict set WEB_colour_map lightcoral 240-128-128 ;# #F08080
dict set WEB_colour_map salmon 250-128-114 ;# #FA8072
dict set WEB_colour_map darksalmon 233-150-122 ;# #E9967A
dict set WEB_colour_map lightsalmon 255-160-122 ;# #FFA07A
# -- --- ---
#Orange colours
dict set WEB_colour_map orangered 255-69-0 ;# #FF4500
dict set WEB_colour_map tomato 255-99-71 ;# #FF6347
dict set WEB_colour_map darkorange 255-140-0 ;# #FF8C00
dict set WEB_colour_map coral 255-127-80 ;# #FF7F50
dict set WEB_colour_map orange 255-165-0 ;# #FFA500
# -- --- ---
#Yellow colours
dict set WEB_colour_map darkkhaki 189-183-107 ;# #BDB76B
dict set WEB_colour_map gold 255-215-0 ;# #FFD700
dict set WEB_colour_map khaki 240-230-140 ;# #F0E68C
dict set WEB_colour_map peachpuff 255-218-185 ;# #FFDAB9
#yellow - as above
dict set WEB_colour_map palegoldenrod 238-232-170 ;# #EEE8AA
dict set WEB_colour_map moccasin 255-228-181 ;# #FFE4B5
dict set WEB_colour_map papayawhip 255-239-213 ;# #FFEFD5
dict set WEB_colour_map lightgoldenrodyeallow 250-250-210 ;# #FAFAD2
dict set WEB_colour_map lemonchiffon 255-250-205 ;# #FFFACD
dict set WEB_colour_map lightyellow 255-255-224 ;# #FFFFE0
# -- --- ---
#Brown colours
#maroon as above
dict set WEB_colour_map brown 165-42-42 ;# #A52A2A
dict set WEB_colour_map saddlebrown 139-69-19 ;# #8B4513
dict set WEB_colour_map sienna 160-82-45 ;# #A0522D
dict set WEB_colour_map chocolate 210-105-30 ;# #D2691E
dict set WEB_colour_map darkgoldenrod 184-134-11 ;# #B8860B
dict set WEB_colour_map peru 205-133-63 ;# #CD853F
dict set WEB_colour_map rosybrown 188-143-143 ;# #BC8F8F
dict set WEB_colour_map goldenrod 218-165-32 ;# #DAA520
dict set WEB_colour_map sandybrown 244-164-96 ;# #F4A460
dict set WEB_colour_map tan 210-180-140 ;# #D2B48C
dict set WEB_colour_map burlywood 222-184-135 ;# #DEB887
dict set WEB_colour_map wheat 245-222-179 ;# #F5DEB3
dict set WEB_colour_map navajowhite 255-222-173 ;# #FFDEAD
dict set WEB_colour_map bisque 255-228-196 ;# #FFEfC4
dict set WEB_colour_map blanchedalmond 255-228-196 ;# #FFEfC4
dict set WEB_colour_map cornsilk 255-248-220 ;# #FFF8DC
# -- --- ---
#Purple, violet, and magenta colours
dict set WEB_colour_map indigo 75-0-130 ;# #4B0082
#purple as above
dict set WEB_colour_map darkmagenta 139-0-139 ;# #8B008B
dict set WEB_colour_map darkviolet 148-0-211 ;# #9400D3
dict set WEB_colour_map darkslateblue 72-61-139 ;# #9400D3
dict set WEB_colour_map blueviolet 138-43-226 ;# #8A2BE2
dict set WEB_colour_map darkorchid 153-50-204 ;# #9932CC
#fuchsia as above
dict set WEB_colour_map magenta 255-0-255 ;# #FF00FF - same as fuchsia
dict set WEB_colour_map slateblue 106-90-205 ;# #6A5ACD
dict set WEB_colour_map mediumslateblue 123-104-238 ;# #7B68EE
dict set WEB_colour_map mediumorchid 186-85-211 ;# #BA5503
dict set WEB_colour_map mediumpurple 147-112-219 ;# #9370DB
dict set WEB_colour_map orchid 218-112-214 ;# #DA70D6
dict set WEB_colour_map violet 238-130-238 ;# #EE82EE
dict set WEB_colour_map plum 221-160-221 ;# #DDA0DD
dict set WEB_colour_map thistle 216-191-216 ;# #D88FD8
dict set WEB_colour_map lavender 230-230-150 ;# #E6E6FA
# -- --- ---
#Blue colours
dict set WEB_colour_map midnightblue 25-25-112 ;# #191970
#navy as above
dict set WEB_colour_map darkblue 0-0-139 ;# #00008B
dict set WEB_colour_map mediumblue 0-0-205 ;# #0000CD
#blue as above
dict set WEB_colour_map royalblue 65-105-225 ;# #4169E1
dict set WEB_colour_map steelblue 70-130-180 ;# #4682B4
dict set WEB_colour_map dodgerblue 30-144-255 ;# #1E90FF
dict set WEB_colour_map deepskyblue 0-191-255 ;# #00BFFF
dict set WEB_colour_map cornflowerblue 100-149-237 ;# #6495ED
dict set WEB_colour_map skyblue 135-206-235 ;# #87CEEB
dict set WEB_colour_map lightskyblue 135-206-250 ;# #87CEFA
dict set WEB_colour_map lightsteelblue 176-196-222 ;# #B0C4DE
dict set WEB_colour_map lightblue 173-216-230 ;# #ADD8E6
dict set WEB_colour_map powderblue 176-224-230 ;# #B0E0E6
# -- --- ---
#Cyan colours
#teal as above
dict set WEB_colour_map darkcyan 0-139-139 ;# #008B8B
dict set WEB_colour_map lightseagreen 32-178-170 ;# #20B2AA
dict set WEB_colour_map cadetblue 95-158-160 ;# #5F9EA0
dict set WEB_colour_map darkturquoise 0-206-209 ;# #00CED1
dict set WEB_colour_map mediumturquoise 72-209-204 ;# #48D1CC
dict set WEB_colour_map turquoise 64-224-208 ;# #40E0D0
#aqua as above
dict set WEB_colour_map cyan 0-255-255 ;# #00FFFF - same as aqua
dict set WEB_colour_map aquamarine 127-255-212 ;# #7FFFD4
dict set WEB_colour_map paleturquoise 175-238-238 ;# #AFEEEE
dict set WEB_colour_map lightcyan 224-255-255 ;# #E0FFFF
# -- --- ---
#Green colours
dict set WEB_colour_map darkgreen 0-100-0 ;# #006400
#green as above
dict set WEB_colour_map darkolivegreen 85-107-47 ;# #55682F
dict set WEB_colour_map forestgreen 34-139-34 ;# #228B22
dict set WEB_colour_map seagrean 46-139-87 ;# #2E8B57
#olive as above
dict set WEB_colour_map olivedrab 107-142-35 ;# #6B8E23
dict set WEB_colour_map mediumseagreen 60-179-113 ;# #3CB371
dict set WEB_colour_map limegreen 50-205-50 ;# #32CD32
#lime as above
dict set WEB_colour_map springgreen 0-255-127 ;# #00FF7F
dict set WEB_colour_map mediumspringgreen 0-250-154 ;# #00FA9A
dict set WEB_colour_map darkseagreen 143-188-143 ;# #8FBC8F
dict set WEB_colour_map mediumaquamarine 102-205-170 ;# #66CDAA
dict set WEB_colour_map yellowgreen 154-205-50 ;# #9ACD32
dict set WEB_colour_map lawngreen 124-252-0 ;# #7CFC00
dict set WEB_colour_map chartreuse 127-255-0 ;# #7FFF00
dict set WEB_colour_map lightgreen 144-238-144 ;# #90EE90
dict set WEB_colour_map greenyellow 173-255-47 ;# #ADFF2F
dict set WEB_colour_map palegreen 152-251-152 ;# #98FB98
# -- --- ---
#White colours
dict set WEB_colour_map mistyrose 255-228-225 ;# #FFE4E1
dict set WEB_colour_map antiquewhite 250-235-215 ;# #FAEBD7
dict set WEB_colour_map linen 250-240-230 ;# #FAF0E6
dict set WEB_colour_map beige 245-245-220 ;# #F5F5DC
dict set WEB_colour_map whitesmoke 245-245-245 ;# #F5F5F5
dict set WEB_colour_map lavenderblush 255-240-245 ;# #FFF0F5
dict set WEB_colour_map oldlace 253-245-230 ;# #FDF5E6
dict set WEB_colour_map aliceblue 240-248-255 ;# #F0F8FF
dict set WEB_colour_map seashell 255-245-238 ;# #FFF5EE
dict set WEB_colour_map ghostwhite 248-248-255 ;# #F8F8FF
dict set WEB_colour_map honeydew 240-255-240 ;# #F0FFF0
dict set WEB_colour_map floralwhite 255-250-240 ;# #FFFAF0
dict set WEB_colour_map azure 240-255-255 ;# #F0FFFF
dict set WEB_colour_map mintcream 245-255-250 ;# #F5FFFA
dict set WEB_colour_map snow 255-250-250 ;# #FFFAFA
dict set WEB_colour_map ivory 255-255-240 ;# #FFFFF0
#white as above
# -- --- ---
#Gray and black colours
#black as above
dict set WEB_colour_map darkslategray 47-79-79 ;# #2F4F4F
dict set WEB_colour_map dimgray 105-105-105 ;# #696969
dict set WEB_colour_map slategray 112-128-144 ;# #708090
#gray as above
dict set WEB_colour_map lightslategray 119-136-153 ;# #778899
dict set WEB_colour_map darkgray 169-169-169 ;# #A9A9A9
dict set WEB_colour_map silver 192-192-192 ;# #C0C0C0
dict set WEB_colour_map lightgray 211-211-211 ;# #D3D3D3
dict set WEB_colour_map gainsboro 220-220-220 ;# #DCDCDC
#we should be able to use WEB_colour_map as a base and override only the conflicts for X11 colours ? Review - check if this is true
variable X11_colour_map
set X11_colour_map $WEB_colour_map
dict set X11_colour_map gray 190-190-190 ;# #BEBEBE
dict set X11_colour_map green 0-255-0 ;# #00FF00
dict set X11_colour_map maroon 176-48-96 ;# #B03060
dict set X11_colour_map purple 160-32-240 ;# #A020F0
#Xterm colour names (256 colours)
#lists on web have duplicate names
#these have been renamed here in a systematic way:
#They are suffixed with a dash and a letter e.g second deepskyblue4 -> deepskyblue4-b, third deepskyblue4 -> deepskyblue4-c
#presumably the xterm colour names are not widely used or are used for reverse lookup from rgb to get an approximate name in the case of dupes?
#Review!
#keep duplicate names in the list and map them when building the dict.
#This is an in depth analysis of the xterm colour set which gives names(*) to all of the 256 colours and describes possible indexing by Hue,Luminance,Saturation
#https://www.wowsignal.io/articles/xterm256
#*The names are wildly-imaginative, often unintuitively so, and multiple (5?) given for each colour - so they are unlikely to be of practical use or any sort of standard.
#e.g who is to know that 'Rabbit Paws', 'Forbidden Thrill' and 'Tarsier' refer to a particular shade of pinky-red? (code 95)
#Perhaps it's an indication that colour naming once we get to 256 colours or more is a fool's errand anyway.
#The xterm names are boringly unimaginative - and also have some oddities such as:
# DarkSlateGray1 which looks much more like cyan..
# The greyxx names are spelt with an e - but the darkslategrayX variants use an a. Perhaps that's because they are more cyan than grey and the a is a hint?
# there is no gold or gold2 - but there is gold1 and gold3
#but in general the names bear some resemblance to the colours and are at least somewhat intuitive.
set xterm_names [list\
black\
maroon\
green\
olive\
navy\
purple\
teal\
silver\
grey\
red\
lime\
yellow\
blue\
fuchsia\
aqua\
white\
grey0\
navyblue\
darkblue\
blue3\
blue3\
blue1\
darkgreen\
deepskyblue4\
deepskyblue4\
deepskyblue4\
dodgerblue3\
dodgerblue2\
green4\
springgreen4\
turquise4\
deepskyblue3\
deepskyblue3\
dodgerblue1\
green3\
springgreen3\
darkcyan\
lightseagreen\
deepskyblue2\
deepskyblue1\
green3\
springgreen3\
springgreen2\
cyan3\
darkturquoise\
turquoise2\
green1\
springgreen2\
springgreen1\
mediumspringgreen\
cyan2\
cyan1\
darkred\
deeppink4\
purple4\
purple4\
purple3\
blueviolet\
orange4\
grey37\
mediumpurple4\
slateblue3\
slateblue3\
royalblue1\
chartreuse4\
darkseagreen4\
paleturquoise4\
steelblue\
steelblue3\
cornflowerblue\
chartreuse3\
darkseagreen4\
cadetblue\
cadetblue\
skyblue3\
steelblue1\
chartreuse3\
palegreen3\
seagreen3\
aquamarine3\
mediumturquoise\
steelblue1\
chartreuse2\
seagreen2\
seagreen1\
seagreen1\
aquamarine1\
darkslategray2\
darkred\
deeppink4\
darkmagenta\
darkmagenta\
darkviolet\
purple\
orange4\
lightpink4\
plum4\
mediumpurple3\
mediumpurple3\
slateblue1\
yellow4\
wheat4\
grey53\
lightslategrey\
mediumpurple\
lightslateblue\
yellow4\
darkolivegreen3\
darkseagreen\
lightskyblue3\
lightskyblue3\
skyblue2\
chartreuse2\
darkolivegreen3\
palegreen3\
darkseagreen3\
darkslategray3\
skyblue1\
chartreuse1\
lightgreen\
lightgreen\
palegreen1\
aquamarine1\
darkslategray1\
red3\
deeppink4\
mediumvioletred\
magenta3\
darkviolet\
purple\
darkorange3\
indianred\
hotpink3\
mediumorchid3\
mediumorchid\
mediumpurple2\
darkgoldenrod\
lightsalmon3\
rosybrown\
grey63\
mediumpurple2\
mediumpurple1\
gold3\
darkkhaki\
navajowhite\
grey69\
lightsteelblue3\
lightsteelblue\
yellow3\
darkolivegreen3\
darkseagreen3\
darkseagreen2\
lightcyan3\
lightskyblue1\
greenyellow\
darkolivegreen2\
palegreen1\
darkseagreen2\
darkseagreen1\
paleturquoise1\
red3\
deppink3\
deeppink3\
magenta3\
magenta3\
magenta2\
darkorange3\
indianred\
hotpink3\
hotpink2\
orchid\
mediumorchid1\
orange3\
lightsalmon3\
lightpink3\
pink3\
plum3\
violet\
gold3\
lightgoldenrod3\
tan\
mistyrose3\
thistle3\
plum2\
yellow3\
khaki3\
lightgoldenrod2\
lightyellow3\
grey84\
lightsteelblue1\
yellow2\
darkolivegreen1\
darkolivegreen1\
darkseagreen1\
honeydew2\
lightcyan1\
red1\
deeppink2\
deeppink1\
deeppink1\
magenta2\
magenta1\
orangered1\
indianred1\
indianred1\
hotpink\
hotpink\
mediumorchid1\
darkorange\
salmon1\
lightcoral\
palevioletred1\
orchid2\
orchid1\
orange1\
sandybrown\
lightsalmon1\
lightpink1\
pink1\
plum1\
gold1\
lightgoldenrod2\
lightgoldenrod2\
navajowhite1\
mistyrose1\
thistle1\
yellow1\
lightgoldenrod1\
khaki1\
wheat1\
cornsilk1\
grey100\
grey3\
grey7\
grey11\
grey11\
grey15\
grey19\
grey23\
grey27\
grey30\
grey35\
grey39\
grey42\
grey46\
grey50\
grey54\
grey58\
grey62\
grey66\
grey70\
grey74\
grey78\
grey82\
grey85\
grey89\
grey93\
]
variable TERM_colour_map
set TERM_colour_map [dict create]
set cidx 0
foreach cname $xterm_names {
if {![dict exists $TERM_colour_map $cname]} {
dict set TERM_colour_map $cname $cidx
} else {
set did_rename 0
#start suffixes at '-b'. The base name could be considered the '-a' version - but we don't create it.
foreach {suffix} {b c} {
if {![dict exists $TERM_colour_map $cname-$suffix]} {
dict set TERM_colour_map $cname-$suffix $cidx
set did_rename 1
break
}
}
if {!$did_rename} {
error "Not enough suffixes for duplicate names in xterm colour list. Add more suffixes or review list"
}
}
incr cidx
}
#colour_hex2dec
#conversion of hex to format directly pluggable to ansi rgb format (colon separated e.g for foreground we need "38;2;$r;$g;$b" so we return $r;$g;$b)
#we want to support arbitrary rgb values specified in hex - so a table of 16M+ is probably not a great idea
#hex zero-padded - canonically upper case but mixed or lower accepted
set spacemap [list hl "\uFFFF" vl "\uFFFF" tlc "\uFFFF" blc "\uFFFF" trc "\uFFFF " brc "\uFFFF"] ;# a debug test
set header_frame [textblock::frame -width 0 -type [dict get $ftypes header]\
-ansibase $ansibase_header \
-boxlimits $hlims -boxmap $spacemap $hcell_blank\
]
append part_header $header_frame\n
} else {
#test version
set hw1 [dict get $o_columnstates $cidx maxwidthheaderseen] ;#headers may be masked by spans, or empty - width may depend more on spans than headers in current column
set hw2 [textblock::width $part_header] ;#widest so far
set hw3 [expr {max($hw1,$hw2)}]
set bw [dict get $o_columnstates $cidx maxwidthbodyseen]
set padwidth [expr {max($hw3,$bw)}]
if {[dict exists $column_width_cache $cidx]} {
set hwidth [dict get $column_width_cache $cidx headerwidth]
set padwidth [expr {max($padwidth,$hwidth)}]
}
#test hack - wider helps stop the breaks - but leaves junk spaces and ansiresets beyond the rhs border of table
#print function overflow 0 fixes?
set padwidth 20
#set bline [string repeat \uFFFF $colwidth]
set bline [string repeat \uFFFF $padwidth]
set h_lines [lrepeat $rowh $bline]
set hcell_blank [::join $h_lines \n]
set spacemap [list hl "\uFFFF" vll "\uFFFF" vlr "\uFFFF" tlc "\uFFFF" blc "\uFFFF" trc "\uFFFF " brc "\uFFFF"] ;# a debug test
set header_frame [textblock::frame -width [expr {$padwidth+2}] -type [dict get $ftypes header]\
-ansibase $ansibase_header \
-boxlimits $hlims -boxmap $spacemap $hcell_blank\
]
append part_header $header_frame\n
}
}
incr h
}
@ -1543,30 +1583,56 @@ namespace eval textblock {
set opt_col_ansibase [dict get $o_columndefs $colidx -ansibase] ;#ordinary merge of codes already done in configure_column
set body_ansibase [dict get $o_opts_table -ansibase_body]
set ansibase $body_ansibase$opt_col_ansibase ;#allow col to override body
#set ansibase [punk::ansi::codetype::sgr_merge_singles [list $body_ansibase $opt_col_ansibase]] ;#allow col to override body
set ansibase $body_ansibase$opt_col_ansibase
set body_ansiborder [dict get $o_opts_table -ansiborder_body]
if {[dict get $o_opts_table -frametype] eq "block"} {
#block is the only style where bg colour can fill the frame content area exactly if the L-shaped border elements are styled
#we need to only accept background ansi codes from the columndef ansibase for this
set col_bg [punk::ansi::codetype::sgr_merge [list $opt_col_ansibase] -filter_fg 1] ;#special merge for block borders - don't override fg colours
set col_bg [punk::ansi::codetype::sgr_merge_singles [list $opt_col_ansibase] -filter_fg 1] ;#special merge for block borders - don't override fg colours
set border_ansi $body_ansibase$body_ansiborder$col_bg
} else {
set border_ansi $body_ansibase$body_ansiborder
}
set r 0
foreach c $cells {
set row_ansibase [dict get $o_rowdefs $r -ansibase]
#todo - joinleft,joinright,joindown based on opts in args
#if padchar width (screen width) > 1 - length calculations will not be correct
#we will allow tokens longer than 1 - as the caller may want to post-process on the token whilst preserving previous leading/trailing spaces, e.g with a string map
#The caller may also use ansi within the padchar - although it's unlikely to be efficient.
# -- --- --- --- --- --- --- --- --- ---
set known_whiches [list l left r right c center centre]
set which [string tolower [dict get $opts -which]]
if {$which in [list centre center]} {set which "c"}
if {$which in [list left]} {set which "l"}
if {$which in [list right]} {set which "r"}
if {$which ni $known_whiches} {
error "textblock::pad unrecognised value for -which option. Known values $known_whiches"
set opt_which [string tolower [dict get $opts -which]]
switch -- $opt_which {
center - centre - c {
set which c
}
left - l {
set which l
}
right - r {
set which r
}
default {
error "textblock::pad unrecognised value for -which option. Known values $known_whiches"
}
}
# -- --- --- --- --- --- --- --- --- ---
set width [dict get $opts -width]
set opt_width [dict get $opts -width]
switch -- $opt_width {
"" - auto {
set width auto
}
default {
if {![string is integer -strict $opt_width] || $opt_width < 0} {
error "textblock::pad -width must be an integer >=0"
error "_insert_before_text_or_last_ansi ansisplits list is not a valid resultlist from an ansi split - must be odd number of elements pt,ansi,pt,ansi...pt"
}
set out [list]
set i 0
set i_last_code [expr {[llength $ansisplits]-3}] ;#would normally be -2 - but our i is jumping to each pt - not every element
foreach {pt code} $ansisplits {
if {$pt ne ""} {
return [lappend out $str {*}[lrange $ansisplits $i end]]
}
if {$i == $i_last_code} {
return [lappend out $str {*}[lrange $ansisplits $i end]]
}
#code being empty can only occur when we have reached last pt