Module:Color2dec: Difference between revisions
From Neodyland Wiki
More actions
m format |
m Protected "Module:Color2dec": Widely used Lua-module ([Edit=Allow only template editors and administrators] (indefinite) [Move=Allow only template editors and administrators] (indefinite)) |
||
| (50 intermediate revisions by one other user not shown) | |||
| Line 1: | Line 1: | ||
-- | --The function "tincture" converts valid tincture names to hexadecimal colorcodes | ||
-- #bbccdd gives 187| | -- e.g. 'argent' will give '#FFF'; when not found it tries afterwards with module:convCSS | ||
--The function "convert" converts a valid hexadecimal colorcode into three decimal numbers: | |||
-- #bbccdd gives 187|204|221, while #FF0 will give 255|255|0 | |||
--The function "tbcgen" generates a complete 5-parameter string | |||
--Invalid color codes will give invalid or unpredictable results, or LUA errors. | --Invalid color codes will give invalid or unpredictable results, or LUA errors. | ||
local p = {} | local p = {} | ||
-- local / global function: convert h → d: #rrggbb or #rgb to dec_table {rr, gg, bb} | |||
local function convert ( arg ) | |||
local hex = arg or '#000'; | |||
if mw.ustring.sub ( hex, 1, 1) ~= '#' then | |||
error ('value "' .. hex .. '" cannot be converted to decimal') | |||
end | |||
local dec = {}; | |||
for i = 1, 3 do | |||
if #hex == 4 then | |||
dec [i] = tonumber ( string.sub (hex, i+1, i+1)..string.sub (hex, i+1, i+1), 16 ) | |||
else | |||
dec [i] = tonumber ( mw.ustring.sub (hex, 2*i, 2*i + 1), 16 ) | |||
end | |||
end | |||
return dec; | |||
end -- function convert | |||
local function | -- global=args[1], local=frame | ||
function p.tincture ( frame ) | |||
local args = frame.args | |||
local | local inp = '' | ||
if args then | |||
inp = mw.text.trim ( args[1] or 'glo' ) | |||
elseif frame then | |||
inp = mw.text.trim ( frame or 'loc' ) | |||
-- else inp = 'Tinct wo' | |||
end | |||
if mw.ustring.sub ( inp, 2, 2 ) == ')' then | |||
inp = mw.ustring.sub ( inp, 3 ) | |||
end | |||
local low = ( string.lower ( inp ) ); | |||
if mw.ustring.sub ( inp, 1, 1 ) == '#' then | |||
if #inp == 4 then | |||
return inp; | |||
elseif mw.ustring.sub ( low, 2, 2 ) == mw.ustring.sub ( low, 3, 3 ) | |||
and mw.ustring.sub ( low, 4, 4 ) == mw.ustring.sub ( low, 5, 5 ) | |||
and mw.ustring.sub ( low, 6, 6 ) == mw.ustring.sub ( low, 7, 7 ) then | |||
local upc = ( string.upper ( inp ) ); | |||
return '#' .. mw.ustring.sub ( upc, 2, 2 ) | |||
.. mw.ustring.sub ( upc, 4, 4 ) | |||
.. mw.ustring.sub ( upc, 6, 6 ); | |||
else | |||
return inp; | |||
end | |||
end | |||
local out = ''; | |||
if low == 'argent' then out = '#FFF' | |||
elseif low == 'argent-d' then out = '#E7E7E7' | |||
elseif low == 'azure' then out = '#0F47AF' | |||
elseif low == 'carnation' then out = '#F2A772' | |||
elseif low == 'céleste' then out = '#89C5E3' | |||
elseif low == 'celeste' then out = '#89C5E3' | |||
elseif low == 'cendrée' then out = '#999' | |||
elseif low == 'gules' then out = '#DA121A' | |||
elseif low == 'naranja' then out = '#EB7711' | |||
elseif low == 'or' then out = '#FCDD09' | |||
elseif low == 'purpure' then out = '#9116A1' | |||
elseif low == 'sable' then out = '#000' | |||
elseif low == 'tawny' then out = '#9D5333' | |||
elseif low == 'vert' then out = '#078930' | |||
-- less common tinctures: | |||
elseif low == 'brunâtre' then out = '#9D5333' | |||
elseif low == 'sanguine' then out = '#C00000' | |||
elseif low == 'murrey' then out = '#800040' | |||
elseif low == 'orange_t' then out = '#FC7A11' | |||
else | |||
local convc = require( "Module:convCSS" ) | |||
out = convc.main ( low ) | |||
end | |||
return out; | |||
end -- function tincture | |||
-- global=args[1], local=frame | |||
function p.decode ( frame ) | |||
local args = frame.args | |||
local str = '' | |||
if args then | |||
str = mw.text.trim ( args [1], charset ); | |||
elseif frame then | |||
str = mw.text.trim ( frame, charset ); | |||
end | |||
if mw.ustring.sub ( str, 2, 2 ) == ')' then | |||
str = mw.ustring.sub ( str, 3 ); -- striped legend | |||
end | end | ||
return | if mw.ustring.sub ( str, 1, 1 ) == '#' then | ||
end | return '#' .. mw.ustring.sub( str, 2 ); | ||
elseif mw.ustring.sub ( str, 1, 1 ) == '*' then | |||
return '*' .. mw.ustring.sub( str, 2 ); | |||
elseif mw.ustring.sub ( str, 1, 1 ) == ':' then | |||
return ':' .. mw.ustring.sub( str, 2 ); | |||
elseif mw.ustring.sub ( str, 1, 1 ) == ';' then | |||
return ';' .. mw.ustring.sub( str, 2 ); | |||
elseif mw.ustring.sub ( str, 1, 1 ) == '_' then | |||
return ' ' .. mw.ustring.sub( str, 2 ); | |||
else | |||
return str; | |||
end | |||
end -- function decode | |||
---- Global functions -------------- | |||
-- global function with 1 parm for Igen/cbox with "#" | |||
function p.tindec ( frame ) | |||
local gpar = frame.args; | |||
local hcod = p.tincture ( gpar[1] ); | |||
return p.decode ( hcod ); | |||
end -- function tindec | |||
-- global function with 1 parm for Igen/cbox | |||
function p.stripe ( frame ) | |||
local | local gpar = frame.args; | ||
if | if mw.ustring.sub ( gpar[1], 2, 2 ) == ')' then | ||
return mw.ustring.sub ( gpar[1], 1, 1 ) | |||
else | else | ||
return '' | |||
end | end | ||
end -- function stripe | |||
end | |||
-- | -- global function with 1 parm for template:F | ||
function p. | function p.remprf ( frame ) | ||
local | local gpar = frame.args; | ||
if mw.ustring.sub (gpar[1], 1, 2) == '()' | |||
or mw.ustring.sub (gpar[1], 1, 2) == '<>' | |||
or mw.ustring.sub (gpar[1], 1, 2) == '[]' | |||
or mw.ustring.sub (gpar[1], 1, 2) == '{}' | |||
or mw.ustring.sub (gpar[1], 1, 1) == mw.ustring.sub (gpar[1], 2, 2) | |||
and mw.ustring.sub (gpar[1], 1, 2) ~= '[[' | |||
and mw.ustring.sub (gpar[1], 1, 2) ~= '{{' then | |||
return mw.ustring.sub (gpar[1], 3 ); -- remove that prefix | |||
elseif mw.ustring.sub (gpar[1], 1, 1) == '_' then | |||
return ' ' .. mw.ustring.sub (gpar[1], 2 ); -- leading space | |||
else | else | ||
return gpar[1]; | |||
end | |||
end -- function remprf | |||
end | |||
return | -- global function with 1 parm -- remove 2-byte prefix | ||
end | function p.rem2bp ( frame ) | ||
local gpar = frame.args; | |||
return mw.ustring.sub (gpar[1], 3 ) | |||
end -- function rem2bp | |||
-- global with 2 parms: count occurencies of pattern in string | |||
function p.count ( frame ) | |||
local gprm = frame.args; -- global parms | |||
-- local strg = mw.text.trim ( gprm[1] or ' ' ) or ' ' ; | |||
-- local pttn = mw.text.trim ( gprm[2] or ' ' ) or ' ' ; | |||
local strg = gprm[1] or ' '; | |||
local pttn = gprm[2] or ' '; | |||
local addp = #pttn - 1; | |||
local cunt = 0; | |||
for i = 1, #strg-addp do | |||
if mw.ustring.sub( strg, i, i+addp) == pttn | |||
then cunt = cunt + 1; | |||
end | |||
end | |||
return cunt -- number of occurrencies | |||
end -- function count | |||
-- global with 2 parms: return left part of string | |||
function p.leftp ( frame ) | |||
local gprm = frame.args; -- global parms | |||
local strg = gprm[1] or ' '; | |||
local pttn = gprm[2] or ' '; | |||
local retv = ''; | |||
for i = 1, #strg do | |||
if mw.ustring.sub( strg, i, i) == pttn | |||
then retv = mw.ustring.sub( strg, 1, i-1); | |||
break; | |||
end | |||
end | |||
return retv -- string | |||
end -- function leftp | |||
-- global with 2 parms: return right part of string | |||
function p.rigtp ( frame ) | |||
local gprm = frame.args; -- global parms | |||
local strg = gprm[1] or ' '; | |||
local pttn = gprm[2] or ' '; | |||
local retv = ''; | |||
for i = 1, #strg do | |||
if mw.ustring.sub( strg, i, i) == pttn | |||
then retv = mw.ustring.sub( strg, i+1, #strg); | |||
break; | |||
end | |||
end | |||
return retv -- string | |||
end -- function rigtp | |||
-- global with 2 parms | |||
function p.tbcgen ( frame ) | |||
local args = frame.args; | |||
local arg1 = args[1] or '#000000'; | |||
local tbctab = {}; | |||
local hexcod = ''; | |||
hexcod = p.tincture ( arg1 ); | |||
decval = convert ( hexcod ); | |||
tbctab [1] = '0'; | |||
tbctab [2] = decval [1]; | |||
tbctab [3] = decval [2]; | |||
tbctab [4] = decval [3]; | |||
tbctab [5] = p.decode ( args[2] or 'couleur' ); | |||
return mw.getCurrentFrame():expandTemplate{ title = 'Tbc', args = tbctab }; | |||
end | |||
-- for template: ColorString | |||
-- two different possibilities for parent parameter input: | |||
-- first parameter has the format aaa/bbb/ccc... (also with html-reserved characters!) | |||
-- second parameter: the name of the template to be performed (default: Igen/cbx) | |||
-- or | |||
-- parameters in the format aaa|bbb|ccc... (allows to specify items like URLs with slashes) | |||
-- In any case the template to be performed can be specified with "t=" | |||
-- returns [to the template] the parameters in the format aaa|bbb|ccc... | |||
-- parent-global parms "ppar" for ColorString | |||
function p.cstring ( frame ) | |||
local pparms = mw.getCurrentFrame(): getParent().args; | |||
local argstr = mw.text.trim( pparms[1] ) or 'aa/bb/cc'; | |||
local argtit = mw.text.trim( pparms.t or 'Igen/cbx' ); | |||
local argtab = mw.text.split( argstr, "/" ); | |||
if mw.text.trim( argtab[1] ) == mw.text.trim( pparms[1] ) then | |||
argtab = pparms | |||
end | |||
return mw.getCurrentFrame(): expandTemplate { title = argtit, args = argtab }; | |||
end -- function cstring | |||
-- global function colortst (1 param) | |||
function p.colorts ( frame ) | |||
local args = frame.args; | |||
local hcod = p.tincture ( args[1] ); | |||
local dtab = convert ( hcod ) | |||
local xsum = dtab [1] + dtab [2] + dtab [3] | |||
local par1 = 'b' | |||
local tsum = tostring ( xsum ) | |||
if #tsum < 3 then tsum = '0' .. tsum end | |||
if #tsum < 3 then tsum = '0' .. tsum end | |||
tsum = ' '..tsum..' ' | |||
if xsum < 408 then par1 = 'w' end | |||
local otab = {} | |||
table.insert(otab, frame:expandTemplate{ title = 'Color', args = { par1, tsum , hcod, hcod } }); | |||
return table.concat (otab) -- args[1] | |||
end -- function colorts | |||
-------------------------------------------------------------------------------- | |||
-- function of Ud:PerfektesChaos (layout: Ud:Sarang), | |||
-- generates a table of 16 × 16 × 16 = 4096 elements | |||
function p.colortab () | |||
local iR, iG, iB, hR, hG, hB, h, s, g | |||
local r = "___NOTOC__" | |||
for iR = 0, 15 do | |||
hR = string.format( "%X", iR ) | |||
r = r .. "\n=== " .. hR .. "xx" | |||
r = r .. " ===\n<table width='100%' border='0' style='text-align:center'>" | |||
for iG = 0, 15 do | |||
hG = string.format( "%X", iG ) | |||
r = r .. "\n<tr>" | |||
for iB = 0, 15 do | |||
hB = string.format( "%X", iB ) | |||
h = hR .. hG .. hB | |||
-- s = contrast( '#'..h ) | |||
-- s = '#' .. string.format( "%X", 15 - iR ) .. string.format( "%X", 15 - iG ) .. string.format( "%X", 15 - iB ) | |||
-- if iR * 2 + iG * 7 + iB < 75 | |||
-- if iR * 3 + iG * 10 < 98 | |||
if iR + iG + iB < 24 | |||
then s = "FFF" else s = "000" end | |||
g = h | |||
if mw.ustring.find("0369CF", hR) ~= nil and | |||
mw.ustring.find("0369CF", hG) ~= nil and | |||
mw.ustring.find("0369CF", hB) ~= nil then | |||
g = "'''" .. g .. "'''" | |||
end | |||
r = r .. string.format( "\n<td title='#%s' style='background:#%s;color:#%s'>%s</td>", h, h, s, g ) | |||
end -- for iB | |||
r = r .. "\n</tr>" | |||
end -- for iG | |||
r = r .. "\n</table>" | |||
end -- for iR | |||
return r | |||
end -- function colortab | |||
return p; | return p; | ||
Latest revision as of 09:12, 29 August 2024
This documentation is transcluded from Module:Color2dec/doc.
--The function "tincture" converts valid tincture names to hexadecimal colorcodes
-- e.g. 'argent' will give '#FFF'; when not found it tries afterwards with module:convCSS
--The function "convert" converts a valid hexadecimal colorcode into three decimal numbers:
-- #bbccdd gives 187|204|221, while #FF0 will give 255|255|0
--The function "tbcgen" generates a complete 5-parameter string
--Invalid color codes will give invalid or unpredictable results, or LUA errors.
local p = {}
-- local / global function: convert h → d: #rrggbb or #rgb to dec_table {rr, gg, bb}
local function convert ( arg )
local hex = arg or '#000';
if mw.ustring.sub ( hex, 1, 1) ~= '#' then
error ('value "' .. hex .. '" cannot be converted to decimal')
end
local dec = {};
for i = 1, 3 do
if #hex == 4 then
dec [i] = tonumber ( string.sub (hex, i+1, i+1)..string.sub (hex, i+1, i+1), 16 )
else
dec [i] = tonumber ( mw.ustring.sub (hex, 2*i, 2*i + 1), 16 )
end
end
return dec;
end -- function convert
-- global=args[1], local=frame
function p.tincture ( frame )
local args = frame.args
local inp = ''
if args then
inp = mw.text.trim ( args[1] or 'glo' )
elseif frame then
inp = mw.text.trim ( frame or 'loc' )
-- else inp = 'Tinct wo'
end
if mw.ustring.sub ( inp, 2, 2 ) == ')' then
inp = mw.ustring.sub ( inp, 3 )
end
local low = ( string.lower ( inp ) );
if mw.ustring.sub ( inp, 1, 1 ) == '#' then
if #inp == 4 then
return inp;
elseif mw.ustring.sub ( low, 2, 2 ) == mw.ustring.sub ( low, 3, 3 )
and mw.ustring.sub ( low, 4, 4 ) == mw.ustring.sub ( low, 5, 5 )
and mw.ustring.sub ( low, 6, 6 ) == mw.ustring.sub ( low, 7, 7 ) then
local upc = ( string.upper ( inp ) );
return '#' .. mw.ustring.sub ( upc, 2, 2 )
.. mw.ustring.sub ( upc, 4, 4 )
.. mw.ustring.sub ( upc, 6, 6 );
else
return inp;
end
end
local out = '';
if low == 'argent' then out = '#FFF'
elseif low == 'argent-d' then out = '#E7E7E7'
elseif low == 'azure' then out = '#0F47AF'
elseif low == 'carnation' then out = '#F2A772'
elseif low == 'céleste' then out = '#89C5E3'
elseif low == 'celeste' then out = '#89C5E3'
elseif low == 'cendrée' then out = '#999'
elseif low == 'gules' then out = '#DA121A'
elseif low == 'naranja' then out = '#EB7711'
elseif low == 'or' then out = '#FCDD09'
elseif low == 'purpure' then out = '#9116A1'
elseif low == 'sable' then out = '#000'
elseif low == 'tawny' then out = '#9D5333'
elseif low == 'vert' then out = '#078930'
-- less common tinctures:
elseif low == 'brunâtre' then out = '#9D5333'
elseif low == 'sanguine' then out = '#C00000'
elseif low == 'murrey' then out = '#800040'
elseif low == 'orange_t' then out = '#FC7A11'
else
local convc = require( "Module:convCSS" )
out = convc.main ( low )
end
return out;
end -- function tincture
-- global=args[1], local=frame
function p.decode ( frame )
local args = frame.args
local str = ''
if args then
str = mw.text.trim ( args [1], charset );
elseif frame then
str = mw.text.trim ( frame, charset );
end
if mw.ustring.sub ( str, 2, 2 ) == ')' then
str = mw.ustring.sub ( str, 3 ); -- striped legend
end
if mw.ustring.sub ( str, 1, 1 ) == '#' then
return '#' .. mw.ustring.sub( str, 2 );
elseif mw.ustring.sub ( str, 1, 1 ) == '*' then
return '*' .. mw.ustring.sub( str, 2 );
elseif mw.ustring.sub ( str, 1, 1 ) == ':' then
return ':' .. mw.ustring.sub( str, 2 );
elseif mw.ustring.sub ( str, 1, 1 ) == ';' then
return ';' .. mw.ustring.sub( str, 2 );
elseif mw.ustring.sub ( str, 1, 1 ) == '_' then
return ' ' .. mw.ustring.sub( str, 2 );
else
return str;
end
end -- function decode
---- Global functions --------------
-- global function with 1 parm for Igen/cbox with "#"
function p.tindec ( frame )
local gpar = frame.args;
local hcod = p.tincture ( gpar[1] );
return p.decode ( hcod );
end -- function tindec
-- global function with 1 parm for Igen/cbox
function p.stripe ( frame )
local gpar = frame.args;
if mw.ustring.sub ( gpar[1], 2, 2 ) == ')' then
return mw.ustring.sub ( gpar[1], 1, 1 )
else
return ''
end
end -- function stripe
-- global function with 1 parm for template:F
function p.remprf ( frame )
local gpar = frame.args;
if mw.ustring.sub (gpar[1], 1, 2) == '()'
or mw.ustring.sub (gpar[1], 1, 2) == '<>'
or mw.ustring.sub (gpar[1], 1, 2) == '[]'
or mw.ustring.sub (gpar[1], 1, 2) == '{}'
or mw.ustring.sub (gpar[1], 1, 1) == mw.ustring.sub (gpar[1], 2, 2)
and mw.ustring.sub (gpar[1], 1, 2) ~= '[['
and mw.ustring.sub (gpar[1], 1, 2) ~= '{{' then
return mw.ustring.sub (gpar[1], 3 ); -- remove that prefix
elseif mw.ustring.sub (gpar[1], 1, 1) == '_' then
return ' ' .. mw.ustring.sub (gpar[1], 2 ); -- leading space
else
return gpar[1];
end
end -- function remprf
-- global function with 1 parm -- remove 2-byte prefix
function p.rem2bp ( frame )
local gpar = frame.args;
return mw.ustring.sub (gpar[1], 3 )
end -- function rem2bp
-- global with 2 parms: count occurencies of pattern in string
function p.count ( frame )
local gprm = frame.args; -- global parms
-- local strg = mw.text.trim ( gprm[1] or ' ' ) or ' ' ;
-- local pttn = mw.text.trim ( gprm[2] or ' ' ) or ' ' ;
local strg = gprm[1] or ' ';
local pttn = gprm[2] or ' ';
local addp = #pttn - 1;
local cunt = 0;
for i = 1, #strg-addp do
if mw.ustring.sub( strg, i, i+addp) == pttn
then cunt = cunt + 1;
end
end
return cunt -- number of occurrencies
end -- function count
-- global with 2 parms: return left part of string
function p.leftp ( frame )
local gprm = frame.args; -- global parms
local strg = gprm[1] or ' ';
local pttn = gprm[2] or ' ';
local retv = '';
for i = 1, #strg do
if mw.ustring.sub( strg, i, i) == pttn
then retv = mw.ustring.sub( strg, 1, i-1);
break;
end
end
return retv -- string
end -- function leftp
-- global with 2 parms: return right part of string
function p.rigtp ( frame )
local gprm = frame.args; -- global parms
local strg = gprm[1] or ' ';
local pttn = gprm[2] or ' ';
local retv = '';
for i = 1, #strg do
if mw.ustring.sub( strg, i, i) == pttn
then retv = mw.ustring.sub( strg, i+1, #strg);
break;
end
end
return retv -- string
end -- function rigtp
-- global with 2 parms
function p.tbcgen ( frame )
local args = frame.args;
local arg1 = args[1] or '#000000';
local tbctab = {};
local hexcod = '';
hexcod = p.tincture ( arg1 );
decval = convert ( hexcod );
tbctab [1] = '0';
tbctab [2] = decval [1];
tbctab [3] = decval [2];
tbctab [4] = decval [3];
tbctab [5] = p.decode ( args[2] or 'couleur' );
return mw.getCurrentFrame():expandTemplate{ title = 'Tbc', args = tbctab };
end
-- for template: ColorString
-- two different possibilities for parent parameter input:
-- first parameter has the format aaa/bbb/ccc... (also with html-reserved characters!)
-- second parameter: the name of the template to be performed (default: Igen/cbx)
-- or
-- parameters in the format aaa|bbb|ccc... (allows to specify items like URLs with slashes)
-- In any case the template to be performed can be specified with "t="
-- returns [to the template] the parameters in the format aaa|bbb|ccc...
-- parent-global parms "ppar" for ColorString
function p.cstring ( frame )
local pparms = mw.getCurrentFrame(): getParent().args;
local argstr = mw.text.trim( pparms[1] ) or 'aa/bb/cc';
local argtit = mw.text.trim( pparms.t or 'Igen/cbx' );
local argtab = mw.text.split( argstr, "/" );
if mw.text.trim( argtab[1] ) == mw.text.trim( pparms[1] ) then
argtab = pparms
end
return mw.getCurrentFrame(): expandTemplate { title = argtit, args = argtab };
end -- function cstring
-- global function colortst (1 param)
function p.colorts ( frame )
local args = frame.args;
local hcod = p.tincture ( args[1] );
local dtab = convert ( hcod )
local xsum = dtab [1] + dtab [2] + dtab [3]
local par1 = 'b'
local tsum = tostring ( xsum )
if #tsum < 3 then tsum = '0' .. tsum end
if #tsum < 3 then tsum = '0' .. tsum end
tsum = ' '..tsum..' '
if xsum < 408 then par1 = 'w' end
local otab = {}
table.insert(otab, frame:expandTemplate{ title = 'Color', args = { par1, tsum , hcod, hcod } });
return table.concat (otab) -- args[1]
end -- function colorts
--------------------------------------------------------------------------------
-- function of Ud:PerfektesChaos (layout: Ud:Sarang),
-- generates a table of 16 × 16 × 16 = 4096 elements
function p.colortab ()
local iR, iG, iB, hR, hG, hB, h, s, g
local r = "___NOTOC__"
for iR = 0, 15 do
hR = string.format( "%X", iR )
r = r .. "\n=== " .. hR .. "xx"
r = r .. " ===\n<table width='100%' border='0' style='text-align:center'>"
for iG = 0, 15 do
hG = string.format( "%X", iG )
r = r .. "\n<tr>"
for iB = 0, 15 do
hB = string.format( "%X", iB )
h = hR .. hG .. hB
-- s = contrast( '#'..h )
-- s = '#' .. string.format( "%X", 15 - iR ) .. string.format( "%X", 15 - iG ) .. string.format( "%X", 15 - iB )
-- if iR * 2 + iG * 7 + iB < 75
-- if iR * 3 + iG * 10 < 98
if iR + iG + iB < 24
then s = "FFF" else s = "000" end
g = h
if mw.ustring.find("0369CF", hR) ~= nil and
mw.ustring.find("0369CF", hG) ~= nil and
mw.ustring.find("0369CF", hB) ~= nil then
g = "'''" .. g .. "'''"
end
r = r .. string.format( "\n<td title='#%s' style='background:#%s;color:#%s'>%s</td>", h, h, s, g )
end -- for iB
r = r .. "\n</tr>"
end -- for iG
r = r .. "\n</table>"
end -- for iR
return r
end -- function colortab
return p;