diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/tabl-xtb.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/tabl-xtb.lua | 986 |
1 files changed, 986 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/context/base/tabl-xtb.lua b/Master/texmf-dist/tex/context/base/tabl-xtb.lua new file mode 100644 index 00000000000..395d65a032c --- /dev/null +++ b/Master/texmf-dist/tex/context/base/tabl-xtb.lua @@ -0,0 +1,986 @@ +if not modules then modules = { } end modules ['tabl-xtb'] = { + version = 1.001, + comment = "companion to tabl-xtb.mkvi", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +--[[ + +This table mechanism is a combination between TeX and Lua. We do process +cells at the TeX end and inspect them at the Lua end. After some analysis +we have a second pass using the calculated widths, and if needed cells +will go through a third pass to get the heights right. This last pass is +avoided when possible which is why some code below looks a bit more +complex than needed. The reason for such optimizations is that each cells +is actually a framed instance and because tables like this can be hundreds +of pages we want to keep processing time reasonable. + +To a large extend the behaviour is comparable with the way bTABLE/eTABLE +works and there is a module that maps that one onto this one. Eventually +this mechamism will be improved so that it can replace its older cousin. + +]]-- + +-- todo: use linked list instead of r/c array + +local texdimen = tex.dimen +local texcount = tex.count +local texbox = tex.box +local texsetcount = tex.setcount +local texsetdimen = tex.setdimen + +local format = string.format +local concat = table.concat +local points = number.points + +local context = context +local context_beginvbox = context.beginvbox +local context_endvbox = context.endvbox +local context_blank = context.blank +local context_nointerlineskip = context.nointerlineskip + +local variables = interfaces.variables + +local setmetatableindex = table.setmetatableindex +local settings_to_hash = utilities.parsers.settings_to_hash + +local copy_node_list = node.copy_list +local hpack_node_list = node.hpack +local vpack_node_list = node.vpack +local slide_node_list = node.slide +local flush_node_list = node.flush_list + +local nodepool = nodes.pool + +local new_glue = nodepool.glue +local new_kern = nodepool.kern +local new_penalty = nodepool.penalty + +local v_stretch = variables.stretch +local v_normal = variables.normal +local v_width = variables.width +local v_height = variables.height +local v_repeat = variables["repeat"] +local v_max = variables.max +local v_fixed = variables.fixed + +local xtables = { } +typesetters.xtables = xtables + +local trace_xtable = false +local report_xtable = logs.reporter("xtable") + +trackers.register("xtable.construct", function(v) trace_xtable = v end) + +local null_mode = 0 +local head_mode = 1 +local foot_mode = 2 +local more_mode = 3 +local body_mode = 4 + +local namedmodes = { [0] = + "null", + "head", + "foot", + "next", + "body", +} + +local stack, data = { }, nil + +function xtables.create(settings) + table.insert(stack,data) + local rows = { } + local widths = { } + local heights = { } + local depths = { } + local spans = { } + local distances = { } + local autowidths = { } + local modes = { } + local fixedrows = { } + local fixedcolumns = { } + local frozencolumns = { } + local options = { } + data = { + rows = rows, + widths = widths, + heights = heights, + depths = depths, + spans = spans, + distances = distances, + modes = modes, + autowidths = autowidths, + fixedrows = fixedrows, + fixedcolumns = fixedcolumns, + frozencolumns = frozencolumns, + options = options, + nofrows = 0, + nofcolumns = 0, + currentrow = 0, + currentcolumn = 0, + settings = settings or { }, + } + local function add_zero(t,k) + t[k] = 0 + return 0 + end + local function add_table(t,k) + local v = { } + t[k] = v + return v + end + local function add_cell(row,c) + local cell = { + nx = 0, + ny = 0, + list = false, + } + row[c] = cell + if c > data.nofcolumns then + data.nofcolumns = c + end + return cell + end + local function add_row(rows,r) + local row = { } + setmetatableindex(row,add_cell) + rows[r] = row + if r > data.nofrows then + data.nofrows = r + end + return row + end + setmetatableindex(rows,add_row) + setmetatableindex(widths,add_zero) + setmetatableindex(heights,add_zero) + setmetatableindex(depths,add_zero) + setmetatableindex(distances,add_zero) + setmetatableindex(modes,add_zero) + setmetatableindex(fixedrows,add_zero) + setmetatableindex(fixedcolumns,add_zero) + setmetatableindex(options,add_table) + -- + settings.columndistance = tonumber(settings.columndistance) or 0 + settings.rowdistance = tonumber(settings.rowdistance) or 0 + settings.leftmargindistance = tonumber(settings.leftmargindistance) or 0 + settings.rightmargindistance = tonumber(settings.rightmargindistance) or 0 + settings.options = settings_to_hash(settings.option) + settings.textwidth = tonumber(settings.textwidth) or tex.hsize + settings.lineheight = tonumber(settings.lineheight) or texdimen.lineheight + settings.maxwidth = tonumber(settings.maxwidth) or settings.textwidth/8 + -- if #stack > 0 then + -- settings.textwidth = tex.hsize + -- end + data.criterium_v = 2 * data.settings.lineheight + data.criterium_h = .75 * data.settings.textwidth + +end + +function xtables.initialize_reflow_width(option) + local r = data.currentrow + local c = data.currentcolumn + 1 + local drc = data.rows[r][c] + drc.nx = texcount.c_tabl_x_nx + drc.ny = texcount.c_tabl_x_ny + local distances = data.distances + local distance = texdimen.d_tabl_x_distance + if distance > distances[c] then + distances[c] = distance + end + if option and option ~= "" then + local options = settings_to_hash(option) + data.options[r][c] = options + if options[v_fixed] then + data.frozencolumns[c] = true + end + end + data.currentcolumn = c +end + +-- local function rather_fixed(n) +-- for n in node. + +function xtables.set_reflow_width() + local r = data.currentrow + local c = data.currentcolumn + local rows = data.rows + local row = rows[r] + while row[c].span do -- can also be previous row ones + c = c + 1 + end + local tb = texbox.b_tabl_x + local drc = row[c] + -- + drc.list = true -- we don't need to keep the content around as we're in trial mode (no: copy_node_list(tb)) + -- + local widths, width = data.widths, tb.width + if width > widths[c] then + widths[c] = width + end + local heights, height = data.heights, tb.height + if height > heights[r] then + heights[r] = height + end + local depths, depth = data.depths, tb.depth + if depth > depths[r] then + depths[r] = depth + end + -- + local dimensionstate = texcount.frameddimensionstate + local fixedcolumns = data.fixedcolumns + local fixedrows = data.fixedrows + if dimensionstate == 1 then + if width > fixedcolumns[c] then -- how about a span here? + fixedcolumns[c] = width + end + elseif dimensionstate == 2 then + fixedrows[r] = height + elseif dimensionstate == 3 then + fixedrows[r] = height -- width + fixedcolumns[c] = width -- height + else -- probably something frozen, like an image -- we could parse the list + if width <= data.criterium_h and height >= data.criterium_v then + if width > fixedcolumns[c] then -- how about a span here? + fixedcolumns[c] = width + end + end + end + drc.dimensionstate = dimensionstate + -- + local nx, ny = drc.nx, drc.ny + if nx > 1 or ny > 1 then + local spans = data.spans + local self = true + for y=1,ny do + for x=1,nx do + if self then + self = false + else + local ry = r + y - 1 + local cx = c + x - 1 + if y > 1 then + spans[ry] = true + end + rows[ry][cx].span = true + end + end + end + c = c + nx - 1 + end + if c > data.nofcolumns then + data.nofcolumns = c + end + data.currentcolumn = c +end + +function xtables.initialize_reflow_height() + local r = data.currentrow + local c = data.currentcolumn + 1 + local rows = data.rows + local row = rows[r] + while row[c].span do -- can also be previous row ones + c = c + 1 + end + data.currentcolumn = c + local widths = data.widths + local w = widths[c] + local drc = row[c] + for x=1,drc.nx-1 do + w = w + widths[c+x] + end + texdimen.d_tabl_x_width = w + local dimensionstate = drc.dimensionstate or 0 + if dimensionstate == 1 or dimensionstate == 3 then + -- width was fixed so height is known + texcount.c_tabl_x_skip_mode = 1 + elseif dimensionstate == 2 then + -- height is enforced + texcount.c_tabl_x_skip_mode = 1 + elseif data.autowidths[c] then + -- width has changed so we need to recalculate the height + texcount.c_tabl_x_skip_mode = 0 + else + texcount.c_tabl_x_skip_mode = 1 + end +end + +function xtables.set_reflow_height() + local r = data.currentrow + local c = data.currentcolumn + local rows = data.rows + local row = rows[r] +-- while row[c].span do -- we could adapt drc.nx instead +-- c = c + 1 +-- end + local tb = texbox.b_tabl_x + local drc = row[c] + if data.fixedrows[r] == 0 then -- and drc.dimensionstate < 2 + local heights, height = data.heights, tb.height + if height > heights[r] then + heights[r] = height + end + local depths, depth = data.depths, tb.depth + if depth > depths[r] then + depths[r] = depth + end + end +-- c = c + drc.nx - 1 +-- data.currentcolumn = c +end + +function xtables.initialize_construct() + local r = data.currentrow + local c = data.currentcolumn + 1 + local rows = data.rows + local row = rows[r] + while row[c].span do -- can also be previous row ones + c = c + 1 + end + data.currentcolumn = c + local widths = data.widths + local heights = data.heights + local depths = data.depths + local w = widths[c] + local h = heights[r] + local d = depths[r] + local drc = row[c] + for x=1,drc.nx-1 do + w = w + widths[c+x] + end + for y=1,drc.ny-1 do + h = h + heights[r+y] + d = d + depths[r+y] + end + texdimen.d_tabl_x_width = w + texdimen.d_tabl_x_height = h + d + texdimen.d_tabl_x_depth = 0 +end + +function xtables.set_construct() + local r = data.currentrow + local c = data.currentcolumn + local rows = data.rows + local row = rows[r] +-- while row[c].span do -- can also be previous row ones +-- c = c + 1 +-- end + local drc = row[c] + -- this will change as soon as in luatex we can reset a box list without freeing + drc.list = copy_node_list(texbox.b_tabl_x) +-- c = c + drc.nx - 1 +-- data.currentcolumn = c +end + +local function showwidths(where,widths,autowidths) + local result = { } + for i=1,#widths do + result[#result+1] = format("%12s%s",points(widths[i]),autowidths[i] and "*" or " ") + end + return report_xtable("%s : %s",where,concat(result," ")) +end + +function xtables.reflow_width() + local nofrows = data.nofrows + local nofcolumns = data.nofcolumns + local rows = data.rows + for r=1,nofrows do + local row = rows[r] + for c=1,nofcolumns do + local drc = row[c] + if drc.list then + --- flush_node_list(drc.list) + drc.list = false + end + end + end + -- spread + local settings = data.settings + local options = settings.options + local maxwidth = settings.maxwidth + -- calculate width + local widths = data.widths + local distances = data.distances + local autowidths = data.autowidths + local fixedcolumns = data.fixedcolumns + local frozencolumns = data.frozencolumns + local width = 0 + local distance = 0 + local nofwide = 0 + local widetotal = 0 + local available = settings.textwidth - settings.leftmargindistance - settings.rightmargindistance + if trace_xtable then + showwidths("stage 1",widths,autowidths) + end + local noffrozen = 0 + if options[v_max] then + for c=1,nofcolumns do + width = width + widths[c] + if width > maxwidth then + autowidths[c] = true + nofwide = nofwide + 1 + widetotal = widetotal + widths[c] + end + if c < nofcolumns then + distance = distance + distances[c] + end + if frozencolumns[c] then + noffrozen = noffrozen + 1 -- brr, should be nx or so + end + end + else + for c=1,nofcolumns do -- also keep track of forced + local fixedwidth = fixedcolumns[c] + if fixedwidth > 0 then + widths[c] = fixedwidth + width = width + fixedwidth + else + width = width + widths[c] + if width > maxwidth then + autowidths[c] = true + nofwide = nofwide + 1 + widetotal = widetotal + widths[c] + end + end + if c < nofcolumns then + distance = distance + distances[c] + end + if frozencolumns[c] then + noffrozen = noffrozen + 1 -- brr, should be nx or so + end + end + end + if trace_xtable then + showwidths("stage 2",widths,autowidths) + end + local delta = available - width - distance - (nofcolumns-1) * settings.columndistance + if delta == 0 then + -- nothing to be done + if trace_xtable then + report_xtable("perfect fit") + end + elseif delta > 0 then + -- we can distribute some + if not options[v_stretch] then + -- not needed + if trace_xtable then + report_xtable("too wide but no stretch, delta: %s",points(delta)) + end + elseif options[v_width] then + local factor = delta / width + if trace_xtable then + report_xtable("proportional stretch, delta: %s, width: %s, factor: %s", + points(delta),points(width),factor) + end + for c=1,nofcolumns do + widths[c] = widths[c] + factor * widths[c] + end + else + -- frozen -> a column with option=fixed will not stretch + local extra = delta / (nofcolumns - noffrozen) + if trace_xtable then + report_xtable("normal stretch, delta: %s, extra: %s", + points(delta),points(extra)) + end + for c=1,nofcolumns do + if not frozencolumns[c] then + widths[c] = widths[c] + extra + end + end + end + elseif nofwide > 0 then + while true do + done = false + local available = (widetotal + delta) / nofwide + if trace_xtable then + report_xtable("shrink check, total: %s, delta: %s, columns: %s, fixed: %s", + points(widetotal),points(delta),nofwide,points(available)) + end + for c=1,nofcolumns do + if autowidths[c] and available >= widths[c] then + autowidths[c] = nil + nofwide = nofwide - 1 + widetotal = widetotal - widths[c] + done = true + end + end + if not done then + break + end + end + -- maybe also options[v_width] here but tricky as width does not say + -- much about amount + + if options[v_width] then -- not that much (we could have a clever vpack loop balancing .. no fun) + local factor = (widetotal + delta) / width + if trace_xtable then + report_xtable("proportional shrink used, total: %s, delta: %s, columns: %s, factor: %s", + points(widetotal),points(delta),nofwide,factor) + end + for c=1,nofcolumns do + if autowidths[c] then + widths[c] = factor * widths[c] + end + end + else + local available = (widetotal + delta) / nofwide + if trace_xtable then + report_xtable("normal shrink used, total: %s, delta: %s, columns: %s, fixed: %s", + points(widetotal),points(delta),nofwide,points(available)) + end + for c=1,nofcolumns do + if autowidths[c] then + widths[c] = available + end + end + end + end + if trace_xtable then + showwidths("stage 3",widths,autowidths) + end + -- + data.currentrow = 0 + data.currentcolumn = 0 +end + +function xtables.reflow_height() + data.currentrow = 0 + data.currentcolumn = 0 + local settings = data.settings + if settings.options[v_height] then + local heights = data.heights + local depths = data.depths + local nofrows = data.nofrows + local totalheight = 0 + local totaldepth = 0 + for i=1,nofrows do + totalheight = totalheight + heights[i] + totalheight = totalheight + depths [i] + end + local total = totalheight + totaldepth + local leftover = settings.textheight - total + if leftover > 0 then + local leftheight = (totalheight / total ) * leftover / #heights + local leftdepth = (totaldepth / total ) * leftover / #depths + for i=1,nofrows do + heights[i] = heights[i] + leftheight + depths [i] = depths [i] + leftdepth + end + end + end +end + +local function showspans(data) + local rows = data.rows + local modes = data.modes + local nofcolumns = data.nofcolumns + local nofrows = data.nofrows + for r=1,nofrows do + local line = { } + local row = rows[r] + for c=1,nofcolumns do + local cell =row[c] + if cell.list then + line[#line+1] = "list" + elseif cell.span then + line[#line+1] = "span" + else + line[#line+1] = "none" + end + end + report_xtable("%3d : %s : %s",r,namedmodes[modes[r]] or "----",concat(line," ")) + end +end + +function xtables.construct() + local rows = data.rows + local heights = data.heights + local depths = data.depths + local widths = data.widths + local spans = data.spans + local distances = data.distances + local modes = data.modes + local settings = data.settings + local nofcolumns = data.nofcolumns + local nofrows = data.nofrows + local columndistance = settings.columndistance + local rowdistance = settings.rowdistance + local leftmargindistance = settings.leftmargindistance + local rightmargindistance = settings.rightmargindistance + -- ranges can be mixes so we collect + + if trace_xtable then + showspans(data) + end + + local ranges = { + [head_mode] = { }, + [foot_mode] = { }, + [more_mode] = { }, + [body_mode] = { }, + } + for r=1,nofrows do + local m = modes[r] + if m == 0 then + m = body_mode + end + local range = ranges[m] + range[#range+1] = r + end + -- todo: hook in the splitter ... the splitter can ask for a chunk of + -- a certain size ... no longer a split memory issue then and header + -- footer then has to happen here too .. target height + local function packaged_column(r) + local row = rows[r] + local start = nil + local stop = nil + if leftmargindistance > 0 then + start = new_kern(leftmargindistance) + stop = start + end + local hasspan = false + for c=1,nofcolumns do + local drc = row[c] + if not hasspan then + hasspan = drc.span + end + local list = drc.list + if list then + list.shift = list.height + list.depth + list = hpack_node_list(list) -- is somehow needed + list.width = 0 + list.height = 0 + list.depth = 0 + if start then + stop.next = list + list.prev = stop + else + start = list + end + stop = list -- one node anyway, so not needed: slide_node_list(list) + end + local step = widths[c] + if c < nofcolumns then + step = step + columndistance + distances[c] + end + local kern = new_kern(step) + if stop then + stop.prev = kern + stop.next = kern + else -- can be first spanning next row (ny=...) + start = kern + end + stop = kern + end + if start then + if rightmargindistance > 0 then + local kern = new_kern(rightmargindistance) + stop.next = kern + kern.prev = stop + -- stop = kern + end + return start, heights[r] + depths[r], hasspan + end + end + local function collect_range(range) + local result, nofr = { }, 0 + local nofrange = #range + for i=1,#range do + local r = range[i] + -- local row = rows[r] + local list, size, hasspan = packaged_column(r) + if list then + if hasspan and nofr > 0 then + result[nofr][4] = true + end + nofr = nofr + 1 + result[nofr] = { + hpack_node_list(list), + size, + i < nofrange and rowdistance > 0 and rowdistance or false, -- might move + false + } + end + end + return result + end + local body = collect_range(ranges[body_mode]) + data.results = { + [head_mode] = collect_range(ranges[head_mode]), + [foot_mode] = collect_range(ranges[foot_mode]), + [more_mode] = collect_range(ranges[more_mode]), + [body_mode] = body, + } + if #body == 0 then + texsetcount("global","c_tabl_x_state",0) + texsetdimen("global","d_tabl_x_final_width",0) + else + texsetcount("global","c_tabl_x_state",1) + texsetdimen("global","d_tabl_x_final_width",body[1][1].width) + end +end + +local function inject(row,copy,package) + local list = row[1] + if copy then + row[1] = copy_node_list(list) + end + if package then + context_beginvbox() + context(list) + context(new_kern(row[2])) + context_endvbox() + context_nointerlineskip() -- figure out a better way + if row[4] then + -- nothing as we have a span + elseif row[3] then + context_blank(row[3] .. "sp") -- why blank ? + else + context(new_glue(0)) + end + else + context(list) + context(new_kern(row[2])) + if row[3] then + context(new_glue(row[3])) + end + end +end + +local function total(row,distance) + local n = #row > 0 and rowdistance or 0 + for i=1,#row do + local ri = row[i] + n = n + ri[2] + (ri[3] or 0) + end + return n +end + +-- local function append(list,what) +-- for i=1,#what do +-- local l = what[i] +-- list[#list+1] = l[1] +-- local k = l[2] + (l[3] or 0) +-- if k ~= 0 then +-- list[#list+1] = new_kern(k) +-- end +-- end +-- end + +local function spanheight(body,i) + local height, n = 0, 1 + while true do + local bi = body[i] + if bi then + height = height + bi[2] + (bi[3] or 0) + if bi[4] then + n = n + 1 + i = i + 1 + else + break + end + else + break + end + end + return height, n +end + +function xtables.flush(directives) -- todo split by size / no inbetween then .. glue list kern blank + local vsize = directives.vsize + local method = directives.method or v_normal + local settings = data.settings + local results = data.results + local rowdistance = settings.rowdistance + local head = results[head_mode] + local foot = results[foot_mode] + local more = results[more_mode] + local body = results[body_mode] + local repeatheader = settings.header == v_repeat + local repeatfooter = settings.footer == v_repeat + if vsize and vsize > 0 then + context_beginvbox() + local bodystart = data.bodystart or 1 + local bodystop = data.bodystop or #body + if bodystart > 0 and bodystart <= bodystop then + local bodysize = vsize + local footsize = total(foot,rowdistance) + local headsize = total(head,rowdistance) + local moresize = total(more,rowdistance) + local firstsize, firstspans = spanheight(body,bodystart) + if bodystart == 1 then -- first chunk gets head + bodysize = bodysize - headsize - footsize + if headsize > 0 and bodysize >= firstsize then + for i=1,#head do + inject(head[i],repeatheader) + end + if rowdistance > 0 then + context(new_glue(rowdistance)) + end + if not repeatheader then + results[head_mode] = { } + end + end + elseif moresize > 0 then -- following chunk gets next + bodysize = bodysize - footsize - moresize + if bodysize >= firstsize then + for i=1,#more do + inject(more[i],true) + end + if rowdistance > 0 then + context(new_glue(rowdistance)) + end + end + elseif headsize > 0 and repeatheader then -- following chunk gets head + bodysize = bodysize - footsize - headsize + if bodysize >= firstsize then + for i=1,#head do + inject(head[i],true) + end + if rowdistance > 0 then + context(new_glue(rowdistance)) + end + end + else -- following chunk gets nothing + bodysize = bodysize - footsize + end + if bodysize >= firstsize then + local i = bodystart + while i <= bodystop do -- room for improvement + local total, spans = spanheight(body,i) + local bs = bodysize - total + if bs > 0 then + bodysize = bs + for s=1,spans do + inject(body[i]) + body[i] = nil + i = i + 1 + end + bodystart = i + else + break + end + end + if bodystart > bodystop then + -- all is flushed and footer fits + if footsize > 0 then + if rowdistance > 0 then + context(new_glue(rowdistance)) + end + for i=1,#foot do + inject(foot[i]) + end + results[foot_mode] = { } + end + results[body_mode] = { } + texsetcount("global","c_tabl_x_state",0) + else + -- some is left so footer is delayed + -- todo: try to flush a few more lines + if repeatfooter and footsize > 0 then + if rowdistance > 0 then + context(new_glue(rowdistance)) + end + for i=1,#foot do + inject(foot[i],true) + end + else + -- todo: try to fit more of body + end + texsetcount("global","c_tabl_x_state",2) + end + else + if firstsize > vsize then + -- get rid of the too large cell + for s=1,firstspans do + inject(body[bodystart]) + body[bodystart] = nil + bodystart = bodystart + 1 + end + end + texsetcount("global","c_tabl_x_state",2) -- 1 + end + else + texsetcount("global","c_tabl_x_state",0) + end + data.bodystart = bodystart + data.bodystop = bodystop + context_endvbox() + else + if method == variables.split then + -- maybe also a non float mode with header/footer repeat although + -- we can also use a float without caption + for i=1,#head do + inject(head[i],false,true) + end + if #head > 0 and rowdistance > 0 then + context_blank(rowdistance .. "sp") + end + for i=1,#body do + inject(body[i],false,true) + end + if #foot > 0 and rowdistance > 0 then + context_blank(rowdistance .. "sp") + end + for i=1,#foot do + inject(foot[i],false,true) + end + else -- normal + context_beginvbox() + for i=1,#head do + inject(head[i]) + end + if #head > 0 and rowdistance > 0 then + context(new_glue(rowdistance)) + end + for i=1,#body do + inject(body[i]) + end + if #foot > 0 and rowdistance > 0 then + context(new_glue(rowdistance)) + end + for i=1,#foot do + inject(foot[i]) + end + context_endvbox() + end + results[head_mode] = { } + results[body_mode] = { } + results[foot_mode] = { } + texsetcount("global","c_tabl_x_state",0) + end +end + +function xtables.cleanup() + for mode, result in next, data.results do + for _, r in next, result do + flush_node_list(r[1]) + end + end + data = table.remove(stack) +end + +function xtables.next_row() + local r = data.currentrow + 1 + data.modes[r] = texcount.c_tabl_x_mode + data.currentrow = r + data.currentcolumn = 0 +end + +-- eventually we might only have commands + +commands.x_table_create = xtables.create +commands.x_table_reflow_width = xtables.reflow_width +commands.x_table_reflow_height = xtables.reflow_height +commands.x_table_construct = xtables.construct +commands.x_table_flush = xtables.flush +commands.x_table_cleanup = xtables.cleanup +commands.x_table_next_row = xtables.next_row +commands.x_table_init_reflow_width = xtables.initialize_reflow_width +commands.x_table_init_reflow_height = xtables.initialize_reflow_height +commands.x_table_init_construct = xtables.initialize_construct +commands.x_table_set_reflow_width = xtables.set_reflow_width +commands.x_table_set_reflow_height = xtables.set_reflow_height +commands.x_table_set_construct = xtables.set_construct |