summaryrefslogtreecommitdiff
path: root/tex
diff options
context:
space:
mode:
authorHans Hagen <pragma@wxs.nl>2012-07-17 00:23:00 +0200
committerHans Hagen <pragma@wxs.nl>2012-07-17 00:23:00 +0200
commitcc4b51097349dc33a2364d2ee87ec9b6b87fdcac (patch)
tree0d44624e0c687bc01eaf618e13545591ed2c57bd /tex
parent830b0c94340c7149db68081a90cd1f0fa9705e14 (diff)
downloadcontext-cc4b51097349dc33a2364d2ee87ec9b6b87fdcac.tar.gz
beta 2012.07.17 00:23
Diffstat (limited to 'tex')
-rw-r--r--tex/context/base/buff-ver.mkiv2
-rw-r--r--tex/context/base/char-ini.lua31
-rw-r--r--tex/context/base/chem-str.mkiv25
-rw-r--r--tex/context/base/cont-new.mkii2
-rw-r--r--tex/context/base/cont-new.mkiv4
-rw-r--r--tex/context/base/context-version.pdfbin4141 -> 4083 bytes
-rw-r--r--tex/context/base/context-version.pngbin106433 -> 106557 bytes
-rw-r--r--tex/context/base/context.mkii2
-rw-r--r--tex/context/base/context.mkiv9
-rw-r--r--tex/context/base/font-sol.lua283
-rw-r--r--tex/context/base/grph-inc.mkiv28
-rw-r--r--tex/context/base/grph-trf.mkiv4
-rw-r--r--tex/context/base/luat-sto.lua3
-rw-r--r--tex/context/base/m-visual.mkiv3
-rw-r--r--tex/context/base/mult-def.mkiv1
-rw-r--r--tex/context/base/mult-low.lua7
-rw-r--r--tex/context/base/mult-sys.mkiv3
-rw-r--r--tex/context/base/node-res.lua12
-rw-r--r--tex/context/base/pack-rul.mkiv2
-rw-r--r--tex/context/base/page-brk.mkiv14
-rw-r--r--tex/context/base/page-col.mkiv174
-rw-r--r--tex/context/base/page-flt.mkiv17
-rw-r--r--tex/context/base/page-ins.lua65
-rw-r--r--tex/context/base/page-ins.mkiv175
-rw-r--r--tex/context/base/page-mix.lua629
-rw-r--r--tex/context/base/page-mix.mkiv754
-rw-r--r--tex/context/base/page-mul.mkiv2209
-rw-r--r--tex/context/base/page-not.mkiv10
-rw-r--r--tex/context/base/page-one.mkiv56
-rw-r--r--tex/context/base/page-otr.mkvi4
-rw-r--r--tex/context/base/page-pst.mkiv4
-rw-r--r--tex/context/base/page-set.mkiv87
-rw-r--r--tex/context/base/page-sid.mkiv5
-rw-r--r--tex/context/base/s-art-01.mkiv4
-rw-r--r--tex/context/base/spac-ver.mkiv10
-rw-r--r--tex/context/base/status-files.pdfbin24464 -> 24333 bytes
-rw-r--r--tex/context/base/status-lua.pdfbin182732 -> 184231 bytes
-rw-r--r--tex/context/base/status-mkiv.lua23
-rw-r--r--tex/context/base/strc-itm.mkvi36
-rw-r--r--tex/context/base/strc-not.mkvi95
-rw-r--r--tex/context/base/strc-reg.lua11
-rw-r--r--tex/context/base/strc-reg.mkiv10
-rw-r--r--tex/context/base/syst-aux.mkiv14
-rw-r--r--tex/context/base/trac-ctx.lua36
-rw-r--r--tex/context/base/trac-ctx.mkiv28
-rw-r--r--tex/context/base/typo-txt.mkvi8
-rw-r--r--tex/context/fonts/demo.lfg29
-rw-r--r--tex/generic/context/luatex/luatex-fonts-merged.lua2
48 files changed, 3389 insertions, 1541 deletions
diff --git a/tex/context/base/buff-ver.mkiv b/tex/context/base/buff-ver.mkiv
index d1385ebd2..5ba0487e9 100644
--- a/tex/context/base/buff-ver.mkiv
+++ b/tex/context/base/buff-ver.mkiv
@@ -366,7 +366,7 @@
\let\inlinemathmarker \textdollar
\def\displaymathmarker{\textdollar\textdollar}
-\def\buff_verbatim_special_type#1#2%
+\def\buff_verbatim_special_type#1#2#% # gobbles spaces
{\dontleavehmode\bgroup
\buff_verbatim_initialize_type_one
\catcode\leftbraceasciicode \begingroupcatcode
diff --git a/tex/context/base/char-ini.lua b/tex/context/base/char-ini.lua
index 244b8d2a7..90e36bc7b 100644
--- a/tex/context/base/char-ini.lua
+++ b/tex/context/base/char-ini.lua
@@ -455,28 +455,37 @@ table we derive a few more.</p>
if not characters.fallbacks then
- -- we could the definition by using a metatable
+ characters.fallbacks = { } -- not than many
- characters.fallbacks = { }
- characters.directions = { }
+ local fallbacks = characters.fallbacks
- local fallbacks = characters.fallbacks
- local directions = characters.directions
-
- for k,v in next, data do
- local specials = v.specials
+ for k, d in next, data do
+ local specials = d.specials
if specials and specials[1] == "compat" and specials[2] == 0x0020 and specials[3] then
local s = specials[3]
fallbacks[k] = s
fallbacks[s] = k
end
- directions[k] = v.direction
end
end
-storage.register("characters/fallbacks", characters.fallbacks, "characters.fallbacks") -- accents and such
-storage.register("characters/directions", characters.directions, "characters.directions")
+storage.register("characters/fallbacks", characters.fallbacks, "characters.fallbacks") -- accents and such
+
+characters.directions = { }
+
+setmetatableindex(characters.directions,function(t,k)
+ local d = data[k]
+ if d then
+ local v = d.direction
+ if v then
+ t[k] = v
+ return v
+ end
+ end
+ t[k] = false -- maybe 'l'
+ return v
+end)
--[[ldx--
<p>The <type>context</type> namespace is used to store methods and data
diff --git a/tex/context/base/chem-str.mkiv b/tex/context/base/chem-str.mkiv
index de1a13bca..aa244d75a 100644
--- a/tex/context/base/chem-str.mkiv
+++ b/tex/context/base/chem-str.mkiv
@@ -58,11 +58,13 @@
\let\setupchemicals\setupchemical
-\unexpanded\def\setupchemicalframed
- {\dosingleempty\dosetupchemicalframed}
+\defineframed
+ [\??chemicalframed]
+ [\c!align=\v!normal,
+ \c!strut=\v!no]
-\def\dosetupchemicalframed
- {\getparameters[\??chemicalframed]}
+\unexpanded\def\setupchemicalframed
+ {\setupframed[\??chemicalframed]}
\unexpanded\def\definechemical % is global (so we don't use the commandhandler)
{\dosingleargument\chem_define}
@@ -171,15 +173,16 @@
\doifelsenothing{\chemicalparameter\c!frame}\chem_framed_nop\chem_framed_yes
\egroup}
-\def\chem_framed_yes
- {\localframed%
+\unexpanded\def\chem_framed_yes
+ {\localframedwithsettings
[\??chemicalframed]%
- [\c!frame=\chemicalparameter\c!frame,\c!align=\v!normal,\c!strut=\v!no]{\vbox{\box\b_chem_result\vss}}} % remove depth
+ [\c!frame=\chemicalparameter\c!frame]%
+ {\vbox{\box\b_chem_result\vss}}} % remove depth
-\def\chem_framed_nop
- {\localframed%
+\unexpanded\def\chem_framed_nop
+ {\directlocalframed
[\??chemicalframed]%
- [\c!align=\v!normal,\c!strut=\v!no]{\vbox{\box\b_chem_result\vss}}} % remove depth
+ {\vbox{\box\b_chem_result\vss}}} % remove depth
\let\startstructurechemical\startchemical
\let\stopstructurechemical \stopchemical
@@ -545,7 +548,7 @@
[\c!align=\v!normal,
\c!strut=\v!no,
\c!offset=\v!overlay,
- \c!frame=off]
+ \c!frame=\v!off]
\setupchemical
[\c!frame=,
diff --git a/tex/context/base/cont-new.mkii b/tex/context/base/cont-new.mkii
index 4ead560b9..9a3834e56 100644
--- a/tex/context/base/cont-new.mkii
+++ b/tex/context/base/cont-new.mkii
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2012.07.10 00:56}
+\newcontextversion{2012.07.17 00:23}
%D This file is loaded at runtime, thereby providing an
%D excellent place for hacks, patches, extensions and new
diff --git a/tex/context/base/cont-new.mkiv b/tex/context/base/cont-new.mkiv
index 57d30209b..03f998078 100644
--- a/tex/context/base/cont-new.mkiv
+++ b/tex/context/base/cont-new.mkiv
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2012.07.10 00:56}
+\newcontextversion{2012.07.17 00:23}
%D This file is loaded at runtime, thereby providing an
%D excellent place for hacks, patches, extensions and new
@@ -215,7 +215,7 @@
#2\expandafter\expandafter\expandafter\doxprecurse\expandafter
\fi\expandafter{\the\numexpr#1-1\relax}{#2}}
-\unexpanded\def\buttonframed{\dodoubleempty\localframed[\??bt]} % goodie
+% \unexpanded\def\buttonframed{\dodoubleempty\localframed[\??bt]} % goodie
\unexpanded\def\asciistr#1{\dontleavehmode{\defconvertedargument\ascii{#1}\verbatimfont\ascii}}
diff --git a/tex/context/base/context-version.pdf b/tex/context/base/context-version.pdf
index 82301750c..3268979c2 100644
--- a/tex/context/base/context-version.pdf
+++ b/tex/context/base/context-version.pdf
Binary files differ
diff --git a/tex/context/base/context-version.png b/tex/context/base/context-version.png
index 225fefee9..7e7b3e6d5 100644
--- a/tex/context/base/context-version.png
+++ b/tex/context/base/context-version.png
Binary files differ
diff --git a/tex/context/base/context.mkii b/tex/context/base/context.mkii
index a0cbec632..8cd630ac1 100644
--- a/tex/context/base/context.mkii
+++ b/tex/context/base/context.mkii
@@ -20,7 +20,7 @@
%D your styles an modules.
\edef\contextformat {\jobname}
-\edef\contextversion{2012.07.10 00:56}
+\edef\contextversion{2012.07.17 00:23}
%D For those who want to use this:
diff --git a/tex/context/base/context.mkiv b/tex/context/base/context.mkiv
index 1e718ca1a..0eb100895 100644
--- a/tex/context/base/context.mkiv
+++ b/tex/context/base/context.mkiv
@@ -25,7 +25,7 @@
%D up and the dependencies are more consistent.
\edef\contextformat {\jobname}
-\edef\contextversion{2012.07.10 00:56}
+\edef\contextversion{2012.07.17 00:23}
%D For those who want to use this:
@@ -146,6 +146,7 @@
\loadmarkfile{trac-tex}
\loadmarkfile{trac-deb}
+\loadmarkfile{trac-ctx} % maybe move up
%loadmarkfile{blob-ini} % not to be used, we only use a helper
@@ -161,8 +162,6 @@
\loadmarkfile{typo-ini}
-\loadmarkfile{page-ins}
-
\loadmkvifile{file-syn}
\loadmkvifile{file-mod}
@@ -261,6 +260,7 @@
\loadmarkfile{page-var}
\loadmkvifile{page-otr}
\loadmarkfile{page-ini}
+\loadmarkfile{page-ins}
\loadmarkfile{page-fac}
\loadmarkfile{page-brk}
\loadmarkfile{page-col}
@@ -279,7 +279,8 @@
\loadmarkfile{page-pst}
\loadmkvifile{page-mbk}
-\loadmarkfile{page-mul}
+\loadmarkfile{page-mul} % partly overloaded
+\loadmarkfile{page-mix} % new
\loadmarkfile{page-set}
\loadmarkfile{pack-lyr}
\loadmarkfile{pack-pos}
diff --git a/tex/context/base/font-sol.lua b/tex/context/base/font-sol.lua
index 861331785..e97e627b4 100644
--- a/tex/context/base/font-sol.lua
+++ b/tex/context/base/font-sol.lua
@@ -41,6 +41,7 @@ local v_normal = variables.normal
local v_reverse = variables.reverse
local v_preroll = variables.preroll
local v_random = variables.random
+local v_split = variables.split
local settings_to_array = utilities.parsers.settings_to_array
local settings_to_hash = utilities.parsers.settings_to_hash
@@ -108,7 +109,8 @@ local preroll = true
local criterium = 0
local randomseed = nil
local optimize = nil -- set later
-local variant = "normal"
+local variant = v_normal
+local splitwords = true
local cache = { }
local variants = { }
@@ -125,23 +127,29 @@ local dummy = {
criterium = 0,
preroll = false,
optimize = nil,
- variant = "normal",
+ splitwords = false,
+ variant = v_normal,
}
local function checksettings(r,settings)
local s = r.settings
local method = settings_to_hash(settings.method or "")
- local optimize
+ local optimize, preroll, splitwords
for k, v in next, method do
- if variants[k] then
+ if k == v_preroll then
+ preroll = true
+ elseif k == v_split then
+ splitwords = true
+ elseif variants[k] then
variant = k
- optimize = variants[k] -- last?
+ optimize = variants[k] -- last one wins
end
end
r.randomseed = tonumber(settings.randomseed) or s.randomseed or r.randomseed or 0
r.criterium = tonumber(settings.criterium ) or s.criterium or r.criterium or 0
- r.preroll = method[v_preroll] and true or false
- r.optimize = optimize or s.optimize or r.optimize
+ r.preroll = preroll or false
+ r.splitwords = splitwords or false
+ r.optimize = optimize or s.optimize or r.optimize or variants[v_normal]
end
local function pushsplitter(name,settings)
@@ -159,6 +167,7 @@ local function pushsplitter(name,settings)
criterium = r.criterium or 0
preroll = r.preroll or false
optimize = r.optimize or nil
+ splitwords = r.splitwords or nil
--
texsetattribute(a_split,r.attribute)
return #stack
@@ -327,22 +336,33 @@ function splitters.split(head)
if m > max_more then max_more = m end
start, stop, done = nil, nil, true
end
- while current do
+ while current do -- also nextid
+ local next = current.next
local id = current.id
- if id == glyph_code and current.subtype < 256 then
- local a = has_attribute(current,a_split)
- if not a then
- start, stop = nil, nil
- elseif not start then
- start, stop, attribute = current, current, a
- elseif a ~= attribute then
- start, stop = nil, nil
- else
- stop = current
+ if id == glyph_code then
+ if current.subtype < 256 then
+ local a = has_attribute(current,a_split)
+ if not a then
+ start, stop = nil, nil
+ elseif not start then
+ start, stop, attribute = current, current, a
+ elseif a ~= attribute then
+ start, stop = nil, nil
+ else
+ stop = current
+ end
end
- current = current.next
elseif id == disc_code then
- start, stop, current = nil, nil, current.next
+ if splitwords then
+ if start then
+ flush()
+ end
+ elseif start and next and next.id == glyph_code and next.subtype < 256 then
+ -- beware: we can cross future lines
+ stop = next
+ else
+ start, stop = nil, nil
+ end
elseif id == whatsit_code then
if start then
flush()
@@ -351,13 +371,12 @@ function splitters.split(head)
if subtype == dir_code or subtype == localpar_code then
rlmode = current.dir
end
- current = current.next
else
if start then
flush()
end
- current = current.next
end
+ current = next
end
if start then
flush()
@@ -370,14 +389,18 @@ end
local function collect_words(list)
local words, w, word = { }, 0, nil
for current in traverse_ids(whatsit_code,list) do
- if current.subtype == userdefined_code then
+ if current.subtype == userdefined_code then -- hm
local user_id = current.user_id
if user_id == splitter_one then
word = { current.value, current, current }
w = w + 1
words[w] = word
elseif user_id == splitter_two then
- word[3] = current
+ if word then
+ word[3] = current
+ else
+ -- something is wrong
+ end
end
end
end
@@ -386,11 +409,36 @@ end
-- we could avoid a hpack but hpack is not that slow
+
+
local function doit(word,list,best,width,badness,line,set,listdir)
local changed = 0
local n = word[1]
local found = cache[n]
if found then
+
+ local h = word[2].next -- head of current word
+ local t = word[3].prev -- tail of current word
+
+ if splitwords then
+ -- there are no lines crossed in a word
+ else
+ local ok = false
+ local c = h
+ while c do
+ if c == t then
+ ok = true
+ break
+ else
+ c = c.next
+ end
+ end
+ if not ok then
+ report_solutions("skipping hyphenated word (for now)")
+ return false, changed
+ end
+ end
+
local original, attribute, direction = found.original, found.attribute, found.direction
local solution = solutions[attribute]
local features = solution and solution[set]
@@ -436,8 +484,8 @@ local function doit(word,list,best,width,badness,line,set,listdir)
report_solutions("fatal error, no dynamics for font %s",font)
end
first = inject_kerns(first)
- local h = word[2].next -- head of current word
- local t = word[3].prev -- tail of current word
+-- local h = word[2].next -- head of current word
+-- local t = word[3].prev -- tail of current word
if first.id == whatsit_code then
local temp = first
first = first.next
@@ -555,112 +603,117 @@ local function show_quality(current,what,line)
end
function splitters.optimize(head)
+ if not optimize then
+ report_optimizers("no optimizer set")
+ return
+ end
local nc = #cache
- if nc > 0 then
- starttiming(splitters)
- local listdir = nil -- todo ! ! !
- if randomseed then
- math.setrandomseedi(randomseed)
- randomseed = nil
- end
- local line = 0
- local tex_hbadness, tex_hfuzz = tex.hbadness, tex.hfuzz
- tex.hbadness, tex.hfuzz = 10000, number.maxdimen
- if trace_optimize then
- report_optimizers("preroll: %s, variant: %s, preroll criterium: %s, cache size: %s",
- tostring(preroll),variant,criterium,nc)
- end
- for current in traverse_ids(hlist_code,head) do
- -- report_splitters("before: [%s] => %s",current.dir,nodes.tosequence(current.list,nil))
- line = line + 1
- local sign, dir, list, width = current.glue_sign, current.dir, current.list, current.width
- local temp, badness = repack_hlist(list,width,'exactly',dir) -- it would be nice if the badness was stored in the node
- if badness > 0 then
- if sign == 0 then
+ if nc == 0 then
+ return
+ end
+ starttiming(splitters)
+ local listdir = nil -- todo ! ! !
+ if randomseed then
+ math.setrandomseedi(randomseed)
+ randomseed = nil
+ end
+ local line = 0
+ local tex_hbadness, tex_hfuzz = tex.hbadness, tex.hfuzz
+ tex.hbadness, tex.hfuzz = 10000, number.maxdimen
+ if trace_optimize then
+ report_optimizers("preroll: %s, variant: %s, preroll criterium: %s, cache size: %s",
+ tostring(preroll),variant,criterium,nc)
+ end
+ for current in traverse_ids(hlist_code,head) do
+ -- report_splitters("before: [%s] => %s",current.dir,nodes.tosequence(current.list,nil))
+ line = line + 1
+ local sign, dir, list, width = current.glue_sign, current.dir, current.list, current.width
+ local temp, badness = repack_hlist(list,width,'exactly',dir) -- it would be nice if the badness was stored in the node
+ if badness > 0 then
+ if sign == 0 then
+ if trace_optimize then
+ report_optimizers("line %s, badness %s, okay",line,badness)
+ end
+ else
+ local set, max
+ if sign == 1 then
if trace_optimize then
- report_optimizers("line %s, badness %s, okay",line,badness)
+ report_optimizers("line %s, badness %s, underfull, trying more",line,badness)
end
+ set, max = "more", max_more
else
- local set, max
- if sign == 1 then
- if trace_optimize then
- report_optimizers("line %s, badness %s, underfull, trying more",line,badness)
- end
- set, max = "more", max_more
- else
- if trace_optimize then
- report_optimizers("line %s, badness %s, overfull, trying less",line,badness)
- end
- set, max = "less", max_less
+ if trace_optimize then
+ report_optimizers("line %s, badness %s, overfull, trying less",line,badness)
end
- -- we can keep the best variants
- local lastbest, lastbadness = nil, badness
- if preroll then
- local bb, base
- for i=1,max do
- if base then
- free_nodelist(base)
- end
- base = copy_nodelist(list)
- local words = collect_words(base) -- beware: words is adapted
- for j=i,max do
- local temp, done, changes, b = optimize(words,base,j,width,badness,line,set,dir)
- base = temp
- if trace_optimize then
- report_optimizers("line %s, alternative: %s.%s, changes: %s, badness %s",line,i,j,changes,b)
- end
- bb = b
- if b <= criterium then
- break
- end
- -- if done then
- -- break
- -- end
+ set, max = "less", max_less
+ end
+ -- we can keep the best variants
+ local lastbest, lastbadness = nil, badness
+ if preroll then
+ local bb, base
+ for i=1,max do
+ if base then
+ free_nodelist(base)
+ end
+ base = copy_nodelist(list)
+ local words = collect_words(base) -- beware: words is adapted
+ for j=i,max do
+ local temp, done, changes, b = optimize(words,base,j,width,badness,line,set,dir)
+ base = temp
+ if trace_optimize then
+ report_optimizers("line %s, alternative: %s.%s, changes: %s, badness %s",line,i,j,changes,b)
end
- if bb and bb > criterium then -- needs checking
- if not lastbest then
- lastbest, lastbadness = i, bb
- elseif bb > lastbadness then
- lastbest, lastbadness = i, bb
- end
- else
+ bb = b
+ if b <= criterium then
break
end
+ -- if done then
+ -- break
+ -- end
end
- free_nodelist(base)
- end
- local words = collect_words(list)
- for best=lastbest or 1,max do
- local temp, done, changes, b = optimize(words,list,best,width,badness,line,set,dir)
- current.list = temp
- if trace_optimize then
- report_optimizers("line %s, alternative: %s, changes: %s, badness %s",line,best,changes,b)
- end
- if done then
- if b <= criterium then -- was == 0
- protect_glyphs(list)
- break
+ if bb and bb > criterium then -- needs checking
+ if not lastbest then
+ lastbest, lastbadness = i, bb
+ elseif bb > lastbadness then
+ lastbest, lastbadness = i, bb
end
+ else
+ break
end
end
+ free_nodelist(base)
end
- else
- if trace_optimize then
- report_optimizers("line %s, not bad enough",line)
+ local words = collect_words(list)
+ for best=lastbest or 1,max do
+ local temp, done, changes, b = optimize(words,list,best,width,badness,line,set,dir)
+ current.list = temp
+ if trace_optimize then
+ report_optimizers("line %s, alternative: %s, changes: %s, badness %s",line,best,changes,b)
+ end
+ if done then
+ if b <= criterium then -- was == 0
+ protect_glyphs(list)
+ break
+ end
+ end
end
end
- -- we pack inside the outer hpack and that way keep the original wd/ht/dp as bonus
- current.list = hpack_nodes(current.list,width,'exactly',listdir)
- -- report_splitters("after: [%s] => %s",temp.dir,nodes.tosequence(temp.list,nil))
- end
- for i=1,nc do
- local ci = cache[i]
- free_nodelist(ci.original)
+ else
+ if trace_optimize then
+ report_optimizers("line %s, not bad enough",line)
+ end
end
- cache = { }
- tex.hbadness, tex.hfuzz = tex_hbadness, tex_hfuzz
- stoptiming(splitters)
+ -- we pack inside the outer hpack and that way keep the original wd/ht/dp as bonus
+ current.list = hpack_nodes(current.list,width,'exactly',listdir)
+ -- report_splitters("after: [%s] => %s",temp.dir,nodes.tosequence(temp.list,nil))
+ end
+ for i=1,nc do
+ local ci = cache[i]
+ free_nodelist(ci.original)
end
+ cache = { }
+ tex.hbadness, tex.hfuzz = tex_hbadness, tex_hfuzz
+ stoptiming(splitters)
end
statistics.register("optimizer statistics", function()
diff --git a/tex/context/base/grph-inc.mkiv b/tex/context/base/grph-inc.mkiv
index 50dab55f0..cc3989491 100644
--- a/tex/context/base/grph-inc.mkiv
+++ b/tex/context/base/grph-inc.mkiv
@@ -264,19 +264,21 @@
\definescale % some day we will inherit
[\v!figure]
- [\c!hfactor =\externalfiguresparameter\c!hfactor,
- \c!wfactor =\externalfiguresparameter\c!wfactor,
- \c!factor =\externalfiguresparameter\c!factor,
- \c!maxwidth =\externalfiguresparameter\c!maxwidth ,
- \c!maxheight=\externalfiguresparameter\c!maxheight,
- \c!xscale =\externalfiguresparameter\c!xscale,
- \c!yscale =\externalfiguresparameter\c!yscale,
- \c!scale =\externalfiguresparameter\c!scale,
- \c!sx =\externalfiguresparameter\c!sx,
- \c!sy =\externalfiguresparameter\c!sy,
- \c!width =\externalfiguresparameter\c!width,
- \c!height =\externalfiguresparameter\c!height,
- \c!lines =\externalfiguresparameter\c!lines]
+ [\c!hfactor =\externalfiguresparameter\c!hfactor,
+ \c!wfactor =\externalfiguresparameter\c!wfactor,
+ \c!factor =\externalfiguresparameter\c!factor,
+ \c!maxwidth =\externalfiguresparameter\c!maxwidth ,
+ \c!maxheight =\externalfiguresparameter\c!maxheight,
+ \c!equalwidth =\externalfiguresparameter\c!equalwidth ,
+ \c!equalheight=\externalfiguresparameter\c!equalheight,
+ \c!xscale =\externalfiguresparameter\c!xscale,
+ \c!yscale =\externalfiguresparameter\c!yscale,
+ \c!scale =\externalfiguresparameter\c!scale,
+ \c!sx =\externalfiguresparameter\c!sx,
+ \c!sy =\externalfiguresparameter\c!sy,
+ \c!width =\externalfiguresparameter\c!width,
+ \c!height =\externalfiguresparameter\c!height,
+ \c!lines =\externalfiguresparameter\c!lines]
%D You can register additional suffixes with the following command:
%D
diff --git a/tex/context/base/grph-trf.mkiv b/tex/context/base/grph-trf.mkiv
index 87193ae4d..dd28f56fb 100644
--- a/tex/context/base/grph-trf.mkiv
+++ b/tex/context/base/grph-trf.mkiv
@@ -506,8 +506,8 @@
\edef#4{\withoutpt\the\scratchdimen}}
% \startcombination
-% {\externalfigure[cow.pdf] [frame=on,height=3cm,equalwidth=6cm]} {}
-% {\externalfigure[mill.png][frame=on,height=3cm,equalwidth=6cm]} {}
+% {\externalfigure[cow.pdf] [frame=on,height=3cm,equalwidth=6cm]} {a cow}
+% {\externalfigure[mill.png][frame=on,height=3cm,equalwidth=6cm]} {a mill}
% \stopcombination
\def\grph_scale_position
diff --git a/tex/context/base/luat-sto.lua b/tex/context/base/luat-sto.lua
index 30bb7d5bb..860aa1121 100644
--- a/tex/context/base/luat-sto.lua
+++ b/tex/context/base/luat-sto.lua
@@ -13,6 +13,7 @@ local gmatch, format, write_nl = string.gmatch, string.format, texio.write_nl
local serialize, concat, sortedhash = table.serialize, table.concat, table.sortedhash
local bytecode = lua.bytecode
+local trace_storage = false
local report_storage = logs.reporter("system","storage")
storage = storage or { }
@@ -63,7 +64,7 @@ local function dump()
max = max + 1
if trace_storage then
report_storage('saving %s in slot %s',message,max)
- c = c + 1 ; code[c] = format("report_storage('restoring %s from slot %s')",message,max)
+ c = c + 1 ; code[c] = format("print('restoring %s from slot %s')",message,max)
end
c = c + 1 ; code[c] = serialize(original,name)
bytecode[max] = loadstring(concat(code,"\n"))
diff --git a/tex/context/base/m-visual.mkiv b/tex/context/base/m-visual.mkiv
index 988276a53..af6bb72fd 100644
--- a/tex/context/base/m-visual.mkiv
+++ b/tex/context/base/m-visual.mkiv
@@ -439,8 +439,7 @@
{\normalhskip -48\points
\normalhbox to 24\points
{\normalhss
- {\ttxx#1}%
- \ruledbaselines
+ {\ttxx\ruledbaselines}%
\normalhskip6\points}%
\raise\scratchdimen\box\scratchbox}%
\smashbox\scratchbox
diff --git a/tex/context/base/mult-def.mkiv b/tex/context/base/mult-def.mkiv
index 433eae9f9..4d3570318 100644
--- a/tex/context/base/mult-def.mkiv
+++ b/tex/context/base/mult-def.mkiv
@@ -71,6 +71,7 @@
\ifdefined\v!stretched \else \def\v!stretched {stretched} \fi
\ifdefined\v!vulgarfraction\else \def\v!vulgarfraction{vulgarfraction} \fi
\ifdefined\v!block \else \def\v!block {block} \fi
+\ifdefined\v!rule \else \def\v!rule {rule} \fi
% stop todo
diff --git a/tex/context/base/mult-low.lua b/tex/context/base/mult-low.lua
index a32d4fe31..fd9493ba1 100644
--- a/tex/context/base/mult-low.lua
+++ b/tex/context/base/mult-low.lua
@@ -137,6 +137,13 @@ return {
--
"then",
--
+ "firstargumentfalse", "firstargumenttrue",
+ "secondargumentfalse", "secondargumenttrue",
+ "thirdargumentfalse", "thirdargumenttrue",
+ "fourthargumentfalse", "fourthargumenttrue",
+ "fifthargumentfalse", "fifthsargumenttrue",
+ "sixthargumentfalse", "sixtsargumenttrue",
+ --
"doglobal", "dodoglobal", "redoglobal", "resetglobal",
--
"donothing", "dontcomplain", "forgetall",
diff --git a/tex/context/base/mult-sys.mkiv b/tex/context/base/mult-sys.mkiv
index de72b5b80..be653f643 100644
--- a/tex/context/base/mult-sys.mkiv
+++ b/tex/context/base/mult-sys.mkiv
@@ -153,6 +153,9 @@
%definesystemconstant {mnem} % kind of generic short tag
+\definesystemconstant {otr}
+\definesystemconstant {box}
+
\definesystemconstant {file}
\definesystemconstant {name}
\definesystemconstant {spec}
diff --git a/tex/context/base/node-res.lua b/tex/context/base/node-res.lua
index 5b2b32a51..4bf4610cd 100644
--- a/tex/context/base/node-res.lua
+++ b/tex/context/base/node-res.lua
@@ -83,7 +83,6 @@ local glue = register_node(new_node("glue")) -- glue.spec = nil
local glue_spec = register_node(new_node("glue_spec"))
local glyph = register_node(new_node("glyph",0))
local textdir = register_node(new_node("whatsit",whatsitcodes.dir))
-local rule = register_node(new_node("rule"))
local latelua = register_node(new_node("whatsit",whatsitcodes.latelua))
local special = register_node(new_node("whatsit",whatsitcodes.special))
local user_n = register_node(new_node("whatsit",whatsitcodes.userdefined)) user_n.type = 100 -- 44
@@ -98,8 +97,12 @@ local leftskip = register_node(new_node("glue",skipcodes.leftskip))
local rightskip = register_node(new_node("glue",skipcodes.rightskip))
local temp = register_node(new_node("temp",0))
local noad = register_node(new_node("noad"))
-local hlist = register_node(new_node("hlist"))
-local vlist = register_node(new_node("vlist"))
+
+-- the dir field needs to be set otherwise crash:
+
+local rule = register_node(new_node("rule")) rule .dir = "TLT"
+local hlist = register_node(new_node("hlist")) hlist.dir = "TLT"
+local vlist = register_node(new_node("vlist")) vlist.dir = "TLT"
function pool.zeroglue(n)
local s = n.spec
@@ -230,8 +233,7 @@ function pool.rule(width,height,depth,dir)
if width then n.width = width end
if height then n.height = height end
if depth then n.depth = depth end
--- if dir then n.dir = dir end
- n.dir = dir or "TLT" -- bug in luatex
+ if dir then n.dir = dir end
return n
end
diff --git a/tex/context/base/pack-rul.mkiv b/tex/context/base/pack-rul.mkiv
index c3ac12b1b..2a1f430ba 100644
--- a/tex/context/base/pack-rul.mkiv
+++ b/tex/context/base/pack-rul.mkiv
@@ -938,7 +938,7 @@
{\bgroup
\dodoubleempty\pack_framed_local}
-\unexpanded\def\localframed[#1][#2]%
+\unexpanded\def\pack_framed_local[#1][#2]%
{\bgroup
\edef\currentframed{#1}%
\pack_framed_initialize
diff --git a/tex/context/base/page-brk.mkiv b/tex/context/base/page-brk.mkiv
index 722556760..ac1fffd6b 100644
--- a/tex/context/base/page-brk.mkiv
+++ b/tex/context/base/page-brk.mkiv
@@ -53,9 +53,9 @@
\def\page_breaks_handle#1%
{\edef\page_breaks_current_options{#1}% handy for tracing
- \processcommacommand[\page_breaks_current_options]\page_breaks_handle_indeed}
+ \processcommacommand[\page_breaks_current_options]\page_breaks_handle_step}
-\def\page_breaks_handle_indeed#1%
+\def\page_breaks_handle_step#1%
{\edef\page_breaks_current_option{#1}% can be used in handler
\ifcsname\??pagebreakmethod\page_breaks_current_option\endcsname
\csname\??pagebreakmethod\page_breaks_current_option\endcsname
@@ -80,7 +80,8 @@
{\setvalue{\??pagebreaks#1}{#2}}
\unexpanded\def\pagebreak
- {\dosingleempty\page_breaks_process}
+ {\par % else no vertical penalties
+ \dosingleempty\page_breaks_process}
\let\page\pagebreak
@@ -269,9 +270,9 @@
\def\page_breaks_columns_handle#1%
{\edef\page_breaks_columns_current_options{#1}%
- \processcommacommand[#1]\page_breaks_columns_handle_indeed}
+ \processcommacommand[#1]\page_breaks_columns_handle_step}
-\def\page_breaks_columns_handle_indeed#1%
+\def\page_breaks_columns_handle_step#1%
{\edef\page_breaks_columns_current_option{#1}%
\ifcsname\??columnbreakmethod\currentoutputroutine:\page_breaks_columns_current_option\endcsname
\csname\??columnbreakmethod\currentoutputroutine:\page_breaks_columns_current_option\endcsname
@@ -296,7 +297,8 @@
{\setvalue{\??columnbreaks#1}{#2}}
\unexpanded\def\columnbreak
- {\dosingleempty\page_breaks_columns_process}
+ {\par % else no vertical penalties
+ \dosingleempty\page_breaks_columns_process}
\let\column\columnbreak
diff --git a/tex/context/base/page-col.mkiv b/tex/context/base/page-col.mkiv
index 3143cadd2..54cf27bc5 100644
--- a/tex/context/base/page-col.mkiv
+++ b/tex/context/base/page-col.mkiv
@@ -19,65 +19,23 @@
\unprotect
-%D The next two registers can be used to store pre column material as well
-%D as footnotes or so.
-
-\newbox\precolumnbox \newdimen\precolumnboxheight
-\newbox\postcolumnbox \newdimen\postcolumnboxheight
-
%D We reserve a counter for the number of columns as well as the current
%D column. Both are not to be changed by users!
\newcount\nofcolumns \nofcolumns\plusone
\newcount\mofcolumns \mofcolumns\plusone
-\setnewconstant\maxnofcolumns 50
-\setnewconstant\allocatednofcolumns 0
-
-%D The next dimensions reports the final column height
-
-\newdimen\finalcolumnheights
-\newcount\finalcolumnlines
-
-%D This register can be used as a temporary storage for page content.
-
-\newbox\restofpage
-
-%D A few more (some might go away):
-
-\newif\ifintermediatefootnotes % seems to be obsolete
-\newif\ifcarryoverfootnotes %\carryoverfootnotestrue
-\newif\iflastcolumnfootnotes %\lastcolumnfootnotestrue
-\newif\ifbalancecolumns %\balancecolumnstrue
-\newif\ifbalancetoheight %\balancetoheighttrue
-\newif\ifforcecolumngrid \forcecolumngridtrue
-\newif\ifstretchcolumns \stretchcolumnsfalse
-\newif\ifinheritcolumns \inheritcolumnsfalse
-\newif\ifheightencolumns \heightencolumnsfalse
-
-\newif\ifbalancingcolumns
-\newif\ifcollectingcontent
-\newif\ifcolumnoverflow
-
-\newdimen\intercolumnwidth
-\newdimen\localcolumnwidth
-\newdimen\savedpagetotal
-
\newconstant\columndirection % 0:lr 1:rl
-\def\minbalancetoplines {1}
-\def\minfreecolumnlines {2}
-
-\newif\ifrecentercolumnbox \recentercolumnboxtrue
-\newif\ifrerecentercolumnbox \rerecentercolumnboxtrue
+\setnewconstant\maxnofcolumns 50
+\setnewconstant\allocatednofcolumns 0
-%D During initialization the temporary boxes are allocated.
-%D This enables us to use as much columns as we want, without
-%D exhausting the pool of boxes too fast. We could have packed
-%D them in one box, but we've got enough boxes.
+%D During initialization the temporary boxes are allocated. This enables us to
+%D use as much columns as we want, without exhausting the pool of boxes too
+%D fast. We could have packed them in one box, but we've got enough boxes.
%D
-%D Two sets of boxes are declared, the txtboxes are used for
-%D the text, the topboxes are for moved column floats.
+%D Two sets of boxes are declared, the txtboxes are used for the text, the
+%D topboxes are for moved column floats.
\installcorenamespace{columntext}
\installcorenamespace{columnfooter}
@@ -92,15 +50,20 @@
\nofcolumns#1\relax
\fi
\ifnum\nofcolumns>\allocatednofcolumns
- \dorecurse\nofcolumns
- {\ifnum\recurselevel>\allocatednofcolumns\relax
+ \page_columns_allocate
+ \fi}
+
+\def\page_columns_allocate
+ {\dorecurse\nofcolumns
+ {\ifnum\recurselevel>\allocatednofcolumns\relax
+ \ifcsname\??columntext\recurselevel\endcsname \else
\expandafter\newbox\csname\??columntext \recurselevel\endcsname % text
\expandafter\newbox\csname\??columnfooter\recurselevel\endcsname % footer
\expandafter\newbox\csname\??columntop \recurselevel\endcsname % top insert
\expandafter\newbox\csname\??columnbottom\recurselevel\endcsname % bottom insert
- \fi}%
- \global\allocatednofcolumns\nofcolumns
- \fi}
+ \fi
+ \fi}%
+ \global\allocatednofcolumns\nofcolumns}
\def\firstcolumnbox {\columntextbox\plusone}
\def\currentcolumnbox {\columntextbox\mofcolumns}
@@ -115,15 +78,15 @@
\def\columntopbox #1{\csname\??columntop \number#1\endcsname}
\def\columnbotbox #1{\csname\??columnbottom\number#1\endcsname}
-\def\columnsettextbox {\global\setbox\columntextbox}
-\def\columnsetfootbox {\global\setbox\columnfootbox}
-\def\columnsettopbox {\global\setbox\columntopbox}
-\def\columnsetbotbox {\global\setbox\columnbotbox}
+\unexpanded\def\columnsettextbox {\global\setbox\columntextbox}
+\unexpanded\def\columnsetfootbox {\global\setbox\columnfootbox}
+\unexpanded\def\columnsettopbox {\global\setbox\columntopbox}
+\unexpanded\def\columnsetbotbox {\global\setbox\columnbotbox}
-\def\columngettextbox {\copy\columntextbox}
-\def\columngetfootbox {\copy\columnfootbox}
-\def\columngettopbox {\copy\columntopbox}
-\def\columngetbotbox {\copy\columnbotbox}
+\unexpanded\def\columngettextbox {\copy\columntextbox}
+\unexpanded\def\columngetfootbox {\copy\columnfootbox}
+\unexpanded\def\columngettopbox {\copy\columntopbox}
+\unexpanded\def\columngetbotbox {\copy\columnbotbox}
\unexpanded\def\columnerasetextboxes{\dorecurse\allocatednofcolumns{\columnsettextbox\recurselevel\emptybox}}
\unexpanded\def\columnerasefootboxes{\dorecurse\allocatednofcolumns{\columnsetfootbox\recurselevel\emptybox}}
@@ -135,25 +98,80 @@
%D with \type {\currentcolumnbox}. In case of the mid columns, \type
%D {\firstcolumnbox} and \type {\lastcolumnbox} are handled outside these macro's.
-%D If needed these can be sped up by using a dedicated loop macro.
+% \unexpanded\def\dohandlecolumn#1%
+% {\mofcolumns\recurselevel
+% \let\currentcolumn\recurselevel
+% #1\relax}
+%
+% \unexpanded\def\dohandleallcolumns#1%
+% {\dorecurse\nofcolumns{\dohandlecolumn{#1}}}
+%
+% \unexpanded\def\dohandlerevcolumns#1%
+% {\dostepwiserecurse\nofcolumns\plusone\minusone{\dohandlecolumn{#1}}}
+%
+% \unexpanded\def\dohandlemidcolumns#1%
+% {\dohandleallcolumns
+% {\ifnum\recurselevel>\plusone
+% \ifnum\recurselevel<\nofcolumns
+% \dohandlecolumn{#1}%
+% \fi
+% \fi}}
+%
+% As we don't nest we can use a fast variant:
+
+\unexpanded\def\dohandleallcolumnscs#1{\let\page_columns_action #1\page_columns_all_indeed}
+\unexpanded\def\dohandleallcolumns #1{\def\page_columns_action{#1}\page_columns_all_indeed}
+
+\unexpanded\def\dohandlerevcolumnscs#1{\let\page_columns_action #1\page_columns_rev_indeed}
+\unexpanded\def\dohandlerevcolumns #1{\def\page_columns_action{#1}\page_columns_rev_indeed}
+
+\unexpanded\def\dohandlemidcolumnscs#1{\let\page_columns_action #1\page_columns_mid_indeed}
+\unexpanded\def\dohandlemidcolumns #1{\def\page_columns_action{#1}\page_columns_mid_indeed}
+
+\unexpanded\def\page_columns_all_indeed
+ {\mofcolumns\plusone
+ \edef\currentcolumn{\the\mofcolumns}%
+ \page_columns_action\relax
+ \ifnum\mofcolumns<\nofcolumns
+ \expandafter\page_columns_all_next
+ \fi}
+
+\unexpanded\def\page_columns_all_next
+ {\advance\mofcolumns\plusone
+ \edef\currentcolumn{\the\mofcolumns}%
+ \page_columns_action\relax
+ \ifnum\mofcolumns<\nofcolumns
+ \expandafter\page_columns_all_next
+ \fi}
-\unexpanded\def\dohandlecolumn#1%
- {\mofcolumns\recurselevel
- \let\currentcolumn\recurselevel
- #1\relax}
+\unexpanded\def\page_columns_rev_indeed
+ {\mofcolumns\nofcolumns
+ \edef\currentcolumn{\the\mofcolumns}%
+ \page_columns_action\relax
+ \ifnum\mofcolumns>\plusone
+ \expandafter\page_columns_rev_prev
+ \fi}
-\unexpanded\def\dohandleallcolumns#1%
- {\dorecurse\nofcolumns{\dohandlecolumn{#1}}}
+\unexpanded\def\page_columns_rev_prev
+ {\advance\mofcolumns\minusone
+ \edef\currentcolumn{\the\mofcolumns}%
+ \page_columns_action\relax
+ \ifnum\mofcolumns>\plusone
+ \expandafter\page_columns_rev_prev
+ \fi}
-\unexpanded\def\dohandlerevcolumns#1%
- {\dostepwiserecurse\nofcolumns\plusone\minusone{\dohandlecolumn{#1}}}
+\unexpanded\def\page_columns_mid_indeed
+ {\mofcolumns\plustwo
+ \ifnum\mofcolumns<\nofcolumns
+ \expandafter\page_columns_mid_next
+ \fi}
-\unexpanded\def\dohandlemidcolumns#1%
- {\dohandleallcolumns
- {\ifnum\recurselevel>\plusone
- \ifnum\recurselevel<\nofcolumns
- \dohandlecolumn{#1}%
- \fi
- \fi}}
+\unexpanded\def\page_columns_mid_next
+ {\edef\currentcolumn{\the\mofcolumns}%
+ \page_columns_action\relax
+ \advance\mofcolumns\plusone
+ \ifnum\mofcolumns<\nofcolumns
+ \expandafter\page_columns_mid_next
+ \fi}
\protect \endinput
diff --git a/tex/context/base/page-flt.mkiv b/tex/context/base/page-flt.mkiv
index c745290d1..56d801072 100644
--- a/tex/context/base/page-flt.mkiv
+++ b/tex/context/base/page-flt.mkiv
@@ -20,15 +20,18 @@
\unprotect
-\installinsertion\c_page_floats_insertions_top
-\installinsertion\c_page_floats_insertions_bottom
+\ifdefined\s!topfloat \else \def\s!topfloat {topfloat} \fi
+\ifdefined\s!bottomfloat \else \def\s!bottomfloat{bottomfloat} \fi
-\newdimen \d_page_floats_inserted_bottom
-\newdimen \d_page_floats_inserted_top
-\newcount \c_page_floats_n_of_top \c_page_floats_n_of_top \plustwo
-\newcount \c_page_floats_n_of_bottom \c_page_floats_n_of_bottom\zerocount
+\defineinsertion[\s!topfloat]
+\defineinsertion[\s!bottomfloat]
-\newconstant \c_page_floats_insertions_topskip_mode % 1 = no topskip
+\newdimen \d_page_floats_inserted_bottom
+\newdimen \d_page_floats_inserted_top
+\newcount \c_page_floats_n_of_top \c_page_floats_n_of_top \plustwo
+\newcount \c_page_floats_n_of_bottom \c_page_floats_n_of_bottom\zerocount
+
+\newconstant\c_page_floats_insertions_topskip_mode % 1 = no topskip
%def\page_floats_report_saved {\showmessage\m!floatblocks2{\the\totalnoffloats}}
\def\page_floats_report_total {\showmessage\m!floatblocks4{\the\totalnoffloats}}
diff --git a/tex/context/base/page-ins.lua b/tex/context/base/page-ins.lua
new file mode 100644
index 000000000..1b8b8583b
--- /dev/null
+++ b/tex/context/base/page-ins.lua
@@ -0,0 +1,65 @@
+if not modules then modules = { } end modules ['page-mix'] = {
+ version = 1.001,
+ comment = "companion to page-mix.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ -- public = {
+ -- functions = {
+ -- "inserts.define",
+ -- "inserts.getdata",
+ -- },
+ -- commands = {
+ -- "defineinsertion",
+ -- "inserttionnumber",
+ -- }
+ -- }
+}
+
+-- Maybe we should only register in lua and forget about the tex end.
+
+structures = structures or { }
+structures.inserts = structures.inserts or { }
+local inserts = structures.inserts
+
+local report_inserts = logs.reporter("inserts")
+
+inserts.stored = inserts.stored or { } -- combining them in one is inefficient in the
+inserts.data = inserts.data or { } -- bytecode storage pool
+
+storage.register("structures/inserts/stored", inserts.stored, "structures.inserts.stored")
+
+local data = inserts.data
+local stored = inserts.stored
+
+for name, specification in next, stored do
+ data[specification.number] = specification
+ data[name] = specification
+end
+
+function inserts.define(specification)
+ local name = specification.name or "unknown"
+ local number = specification.number or 0
+ data[name] = specification
+ data[number] = specification
+ -- only needed at runtime as this get stored in a bytecode register
+ stored[name] = specification
+end
+
+function inserts.getdata(name) -- or number
+ return data[name]
+end
+
+function inserts.getname(number)
+ return data[name].name
+end
+
+function inserts.getnumber(name)
+ return data[name].number
+end
+
+-- interface
+
+commands.defineinsertion = inserts.define
+commands.insertionnumber = function(name) context(data[name].number or 0) end
+
diff --git a/tex/context/base/page-ins.mkiv b/tex/context/base/page-ins.mkiv
index 33c50451b..cb952e6e7 100644
--- a/tex/context/base/page-ins.mkiv
+++ b/tex/context/base/page-ins.mkiv
@@ -17,23 +17,56 @@
%D page builder. When multiple footnote classes were introduced, I decided to
%D isolate some of the functionality in a module.
+\registerctxluafile{page-ins}{1.001}
+
\unprotect
+%D Because we need to deal with inserts at the \LUA\ end as well,
+%D we provide a proper installer.
+
+% Not yet used as we need to adapt some code to this.
+
+\installcorenamespace{insertion}
+\installcorenamespace{insertionnumber}
+
+\installcommandhandler \??insertion {insertion} \??insertion
+
+\newcount\currentinsertionnumber % This is a count and not a macro !
+
\newtoks\t_page_inserts_list
-\let\doprocessinsert\gobbleoneargument
+\let\doprocessinsert\relax
-\unexpanded\def\installinsertion#1%
- {\ifdefined#1\else
- \let#1\relax
- \fi
- \ifx#1\relax % permits \csname...\endcsname
- \newinsert#1%
- \count#1\plusthousand
- \skip #1\zeropoint
- \dimen#1\maxdimen
- \appendtoks\doprocessinsert#1\to\t_page_inserts_list
- \fi}
+%D Maybe some day we will move settings here.
+
+\unexpanded\def\setcurrentinsertion#1%
+ {\edef\currentinsertion{#1}%
+ \currentinsertionnumber\csname\??insertionnumber\currentinsertion\endcsname}
+
+\def\namedinsertionnumber#1{\csname\??insertionnumber#1\endcsname}
+
+\unexpanded\def\page_inserts_synchronize_registers
+ {\currentinsertionnumber\csname\??insertionnumber\currentinsertion\endcsname}
+
+\appendtoks
+ \page_inserts_synchronize_registers
+\to \everysetupinsertion
+
+% \setupinsertion
+% [\c!distance=\zeropoint,
+% \c!maxheight=\maxdimen,
+% \c!factor=\plusthousand]
+%
+% \unexpanded\def\page_inserts_synchronize_registers
+% {\currentinsertionnumber\csname\??insertionnumber\currentinsertion\endcsname
+% \global\count\currentinsertionnumber\insertionparameter\c!factor \relax
+% \global\skip \currentinsertionnumber\insertionparameter\c!distance \relax
+% \global\dimen\currentinsertionnumber\insertionparameter\c!maxheight\relax}
+
+\unexpanded\def\page_inserts_process#1%
+ {\edef\currentinsertion{#1}%
+ \currentinsertionnumber\csname\??insertionnumber\currentinsertion\endcsname
+ \doprocessinsert\currentinsertionnumber} % old method
\unexpanded\def\processinsertions
{\the\t_page_inserts_list}
@@ -42,54 +75,92 @@
{\let\doprocessinsert\page_inserts_synchronize
\processinsertions}
-\def\page_inserts_synchronize#1%
+\unexpanded\def\page_inserts_synchronize#1% yes or no
{\ifvoid#1\else
\insert#1{\unvbox#1}%
\fi}
-%D For instance, when we postpone footnotes, we need to save some data related to
-%D the inserts. The next methods are far from ideal, but better than nothing. We
-%D save and restore box content and associated data independently. The box content
-%D is only restores when non||void.
-
-\installcorenamespace{insertionbackup}
-
-\unexpanded\def\installbackupinsertion#1%
- {\ifcsname\??insertionbackup\string#1\endcsname \else
- \expandafter\newinsert\csname\??insertionbackup\string#1\endcsname
- \count\csname\??insertionbackup\string#1\endcsname\zerocount
- \skip \csname\??insertionbackup\string#1\endcsname\zeropoint
- \dimen\csname\??insertionbackup\string#1\endcsname\maxdimen
- \fi}
-
-\unexpanded\def\saveinsertionbox#1% hm, actually unknown
- {\global\setbox\csname\??insertionbackup\string#1\endcsname
- \ifdim\ht#1>\zeropoint\box#1\else\emptybox\fi}
-
-\unexpanded\def\restoreinsertionbox#1%
- {\ifvoid\backupinsertion#1\else % if void, we keep the content
- \global\setbox#1\box\csname\??insertionbackup\string#1\endcsname
+\unexpanded\def\doifinsertionelse#1%
+ {\ifcsname\??insertionnumber#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
\fi}
-\unexpanded\def\eraseinsertionbackup#1%
- {\global\setbox\csname\??insertionbackup\string#1\endcsname\emptybox}
-
-\unexpanded\def\saveinsertiondata#1%
- {\global\skip \csname\??insertionbackup\string#1\endcsname\skip #1%
- \global\count\csname\??insertionbackup\string#1\endcsname\count#1%
- \global\dimen\csname\??insertionbackup\string#1\endcsname\dimen#1}
-
-\unexpanded\def\restoreinsertiondata#1%
- {\global\skip #1\skip \csname\??insertionbackup\string#1\endcsname
- \global\count#1\count\csname\??insertionbackup\string#1\endcsname
- \global\dimen#1\dimen\csname\??insertionbackup\string#1\endcsname}
+% \unexpanded\def\startinsertion[#1]%
+% {\insert\csname\??insertionnumber#1\endcsname\bgroup}
+%
+% \unexpanded\def\stopinsertion
+% {\egroup}
+
+% For the moment we use the regular insertion allocator so that users can
+% still define their own insertions (not that they will play nicely with
+% all context mechanisms then). We can use the dimensions at the \LUA\ end
+% so we don't need to pass pass them explicitly. Actually, when we see an
+% insertion node at that end, we already know the number.
+
+\appendtoks
+ \ifcsname\??insertionnumber\currentinsertion\endcsname
+ % bad news
+ \else
+ \expandafter\newinsert\csname\??insertionnumber\currentinsertion\endcsname
+ \page_inserts_synchronize_registers
+ \ctxcommand{defineinsertion
+ {
+ name = "\currentinsertion",
+ number = \number\currentinsertionnumber,
+ }
+ }%
+ %
+ \t_page_inserts_list\expandafter\expandafter\expandafter
+ {\expandafter\the\expandafter\t_page_inserts_list
+ \expandafter\page_inserts_process\csname\??insertionnumber\currentinsertion\endcsname}%
+ \count\currentinsertionnumber\plusthousand
+ \skip \currentinsertionnumber\zeropoint
+ \dimen\currentinsertionnumber\maxdimen
+ \fi
+\to \everydefineinsertion
%D Auxiliary macros:
-\unexpanded\def\addinsertionheight#1\to#2%
- {\ifvoid#1\else
- \advance#2 1\skip#1\relax
- \advance#2 \ht #1\relax
- \fi}
+\def\page_insert_insertion_height#1%
+ {\dimexpr\expandafter\page_insert_insertion_height_indeed\csname\??insertionnumber#1\endcsname\relax}
+
+\def\page_insert_insertion_height_indeed#1%
+ {\ifvoid#1\zeropoint\else1\skip#1+\ht#1\fi}
+
+%D Obsolete:
+
+% \installcorenamespace{insertionbackup}
+%
+% \unexpanded\def\installbackupinsertion#1%
+% {\ifcsname\??insertionbackup\string#1\endcsname \else
+% \expandafter\newinsert\csname\??insertionbackup\string#1\endcsname
+% \count\csname\??insertionbackup\string#1\endcsname\zerocount
+% \skip \csname\??insertionbackup\string#1\endcsname\zeropoint
+% \dimen\csname\??insertionbackup\string#1\endcsname\maxdimen
+% \fi}
+%
+% \unexpanded\def\saveinsertionbox#1% hm, actually unknown
+% {\global\setbox\csname\??insertionbackup\string#1\endcsname
+% \ifdim\ht#1>\zeropoint\box#1\else\emptybox\fi}
+%
+% \unexpanded\def\restoreinsertionbox#1%
+% {\ifvoid\backupinsertion#1\else % if void, we keep the content
+% \global\setbox#1\box\csname\??insertionbackup\string#1\endcsname
+% \fi}
+%
+% \unexpanded\def\eraseinsertionbackup#1%
+% {\global\setbox\csname\??insertionbackup\string#1\endcsname\emptybox}
+%
+% \unexpanded\def\saveinsertiondata#1%
+% {\global\skip \csname\??insertionbackup\string#1\endcsname\skip #1%
+% \global\count\csname\??insertionbackup\string#1\endcsname\count#1%
+% \global\dimen\csname\??insertionbackup\string#1\endcsname\dimen#1}
+%
+% \unexpanded\def\restoreinsertiondata#1%
+% {\global\skip #1\skip \csname\??insertionbackup\string#1\endcsname
+% \global\count#1\count\csname\??insertionbackup\string#1\endcsname
+% \global\dimen#1\dimen\csname\??insertionbackup\string#1\endcsname}
\protect \endinput
diff --git a/tex/context/base/page-mix.lua b/tex/context/base/page-mix.lua
new file mode 100644
index 000000000..75e013ce4
--- /dev/null
+++ b/tex/context/base/page-mix.lua
@@ -0,0 +1,629 @@
+if not modules then modules = { } end modules ['page-mix'] = {
+ version = 1.001,
+ comment = "companion to page-mix.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- inserts.getname(name)
+
+-- local node, tex = node, tex
+-- local nodes, interfaces, utilities = nodes, interfaces, utilities
+-- local trackers, logs, storage = trackers, logs, storage
+-- local number, table = number, table
+
+local concat = table.concat
+
+local nodecodes = nodes.nodecodes
+local gluecodes = nodes.gluecodes
+local nodepool = nodes.pool
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local kern_code = nodecodes.kern
+local glue_code = nodecodes.glue
+local penalty_code = nodecodes.penalty
+local insert_code = nodecodes.ins
+local mark_code = nodecodes.mark
+
+local new_hlist = nodepool.hlist
+local new_vlist = nodepool.vlist
+local new_glue = nodepool.glue
+
+local hpack = node.hpack
+local vpack = node.vpack
+local freenode = node.free
+
+local texbox = tex.box
+local texskip = tex.skip
+local texdimen = tex.dimen
+local points = number.points
+local settings_to_hash = utilities.parsers.settings_to_hash
+
+local variables = interfaces.variables
+local v_yes = variables.yes
+local v_global = variables["global"]
+local v_local = variables["local"]
+
+local trace_state = false trackers.register("mixedcolumns.trace", function(v) trace_state = v end)
+local trace_detail = false trackers.register("mixedcolumns.detail", function(v) trace_detail = v end)
+
+local report_state = logs.reporter("mixed columns")
+
+pagebuilders = pagebuilders or { }
+pagebuilders.mixedcolumns = pagebuilders.mixedcolumns or { }
+local mixedcolumns = pagebuilders.mixedcolumns
+
+local forcedbreak = -123
+
+-- initializesplitter(specification)
+-- cleanupsplitter()
+
+local function collectinserts(result,nxt,nxtid)
+ local inserts, currentskips, nextskips, inserttotal = { }, 0, 0, 0
+ while nxt do
+ if nxtid == insert_code then
+ inserttotal = inserttotal + nxt.height + nxt.depth
+ local s = nxt.subtype
+ local c = inserts[s]
+ if not c then
+ c = { }
+ inserts[s] = c
+ local width = texskip[s].width
+ if not result.inserts[s] then
+ currentskips = currentskips + width
+ end
+ nextskips = nextskips + width
+ end
+ c[#c+1] = nxt
+ if trace_detail then
+ report_state("insert of class %s found",s)
+ end
+ elseif nxtid == mark_code then
+ if trace_detail then
+ report_state("mark found")
+ end
+ else
+ break
+ end
+ nxt = nxt.next
+ if nxt then
+ nxtid = nxt.id
+ else
+ break
+ end
+ end
+ return nxt, inserts, currentskips, nextskips, inserttotal
+end
+
+local function appendinserts(ri,inserts)
+ for class, collected in next, inserts do
+ local ric = ri[class]
+ if not ric then
+ -- assign to collected
+ ri[class] = collected
+ else
+ -- append to collected
+ for j=1,#collected do
+ ric[#ric+1] = collected[j]
+ end
+ end
+ end
+end
+
+local function discardtopglue(current,discarded)
+ while current do
+ local id = current.id
+ if id == glue_code or (id == penalty_code and current.penalty ~= forcedbreak) then
+ discarded[#discarded+1] = current
+ current = current.next
+ else
+ break
+ end
+ end
+ return current
+end
+
+local function stripbottomglue(results,discarded)
+ local height = 0
+ for i=1,#results do
+ local r = results[i]
+ local t = r.tail
+ while t and t ~= r.head do
+ local prev = t.prev
+ if not prev then
+ break
+ elseif t.id == penalty_code then
+ if t.penalty == forcedbreak then
+ break
+ else
+ discarded[#discarded+1] = t
+ r.tail = prev
+ t = prev
+ end
+ elseif t.id == glue_code then
+ discarded[#discarded+1] = t
+ r.height = r.height - t.spec.width
+ r.tail = prev
+ t = prev
+ else
+ break
+ end
+ end
+ if r.height > height then
+ height = r.height
+ end
+ end
+ return height
+end
+
+local function setsplit(specification) -- a rather large function
+ local box = specification.box
+ if not box then
+ report_state("fatal error, no box")
+ return
+ end
+ local list = texbox[box]
+ if not list then
+ report_state("fatal error, no list")
+ return
+ end
+ local head = list.head or specification.originalhead
+ if not head then
+ report_state("fatal error, no head")
+ return
+ end
+ local discarded = { }
+ local originalhead = head
+ local originalwidth = specification.originalwidth or list.width
+ local originalheight = specification.originalheight or list.height
+ local current = head
+ local height = 0
+ local depth = 0
+ local skip = 0
+ local options = settings_to_hash(specification.option or "")
+ local stripbottom = specification.alternative == v_local
+ local cycle = specification.cycle or 1
+ local nofcolumns = specification.nofcolumns or 1
+ if nofcolumns == 0 then
+ nofcolumns = 1
+ end
+ local preheight = specification.preheight or 0
+ local extra = specification.extra or 0
+ local maxheight = specification.maxheight
+ local optimal = originalheight/nofcolumns
+ if specification.balance ~= v_yes then
+ optimal = maxheight
+ end
+ local target = optimal + extra
+ local overflow = target > maxheight - preheight
+ local threshold = specification.threshold or 0
+ if overflow then
+ target = maxheight - preheight
+ end
+ if trace_state then
+ report_state("cycle: %s, maxheight: %s, preheight: %s, target: %s, overflow: %s, extra: %s",
+ cycle, points(maxheight),points(preheight),points(target),tostring(overflow),points(extra))
+ end
+ local results = { }
+ for i=1,nofcolumns do
+ results[i] = {
+ head = false,
+ tail = false,
+ height = 0,
+ depth = 0,
+ inserts = { },
+ delta = 0,
+ }
+ end
+ local column = 1
+ local result = results[column]
+ local lasthead = nil
+ local rest = nil
+ local function gotonext()
+ if head == lasthead then
+ if trace_state then
+ report_state("empty column %s, needs more work",column)
+ end
+rest = current
+return false
+ else
+ lasthead = head
+ result.head = head
+ if current == head then
+ result.tail = head
+ else
+ result.tail = current.prev
+ end
+ result.height = height
+ result.depth = depth
+ end
+ head = current
+ height = 0
+ depth = 0
+ skip = 0
+ if column == nofcolumns then
+ column = 0 -- nicer in trace
+ rest = head
+-- lasthead = head
+ return false
+ else
+ column = column + 1
+ result = results[column]
+ current = discardtopglue(current,discarded)
+ head = current
+-- lasthead = head
+ return true
+ end
+ end
+ local function checked(advance)
+ local total = skip + height + depth + advance
+ local delta = total - target
+ if trace_detail then
+ local currentcolumn = column
+ local state
+ if delta > threshold then
+ result.delta = delta
+ if gotonext() then
+ state = "next"
+ else
+ state = "quit"
+ end
+ else
+ state = "same"
+ end
+ if trace_detail then
+ report_state("check > column %s, advance: %s, total: %s, target: %s => %s (height: %s, depth: %s, skip: %s)",
+ currentcolumn,points(advance),points(total),points(target),state,points(height),points(depth),points(skip))
+ end
+ return state
+ else
+ if delta > threshold then
+ result.delta = delta
+ if gotonext() then
+ return "next"
+ else
+ return "quit"
+ end
+ else
+ return "same"
+ end
+ end
+ end
+ current = discardtopglue(current,discarded)
+ head = current
+ while current do
+ local id = current.id
+ local nxt = current.next
+ if id == hlist_code or id == vlist_code then
+ local nxtid = nxt and nxt.id
+ local inserts, currentskips, nextskips, inserttotal = nil, 0, 0, 0
+ local advance = current.height -- + current.depth
+ if nxt and (nxtid == insert_code or nxtid == mark_code) then
+ nxt, inserts, localskips, insertskips, inserttotal = collectinserts(result,nxt,nxtid)
+ end
+ local state = checked(advance+inserttotal+currentskips)
+ if trace_state then
+ report_state('line > column %s, advance: %s, insert: %s, height: %s, state: %s',
+ column,points(advance),points(inserttotal),points(height),state)
+ end
+ if state == "quit" then
+ break
+ else
+ height = height + depth + skip + advance + inserttotal
+ if state == "next" then
+ height = height + nextskips
+ else
+ height = height + currentskips
+ end
+ end
+ depth = current.depth
+ skip = 0
+ if inserts then
+ appendinserts(result.inserts,inserts)
+ end
+ elseif id == glue_code then
+ local advance = current.spec.width
+ if advance ~= 0 then
+ local state = checked(advance)
+ if trace_state then
+ report_state('glue > column %s, advance: %s, height: %s, state: %s',
+ column,points(advance),points(height),state)
+ end
+ if state == "quit" then
+ break
+ end
+ height = height + depth + skip
+ depth = 0
+ skip = height > 0 and advance or 0
+ end
+ elseif id == kern_code then
+ local advance = current.kern
+ if advance ~= 0 then
+ local state = checked(advance)
+ if trace_state then
+ report_state('kern > column %s, advance: %s, height: %s, state: %s',
+ column,points(advance),points(height),state)
+ end
+ if state == "quit" then
+ break
+ end
+ height = height + depth + skip + advance
+ depth = 0
+ skip = 0
+ end
+ elseif id == penalty_code then
+ local penalty = current.penalty
+ if penalty == 0 then
+ -- don't bother
+ elseif penalty == forcedbreak then
+ if gotonext() then
+ if trace_state then
+ report_state("cycle: %s, forced column break (same page)",cycle)
+ end
+ else
+ if trace_state then
+ report_state("cycle: %s, forced column break (next page)",cycle)
+ end
+ break
+ end
+ else
+ -- club and widow and such i.e. resulting penalties (if we care)
+ end
+ end
+ if nxt then
+ current = nxt
+ elseif head == lasthead then
+-- if trace_state then
+-- report_state("quit as head is lasthead")
+-- end
+-- break
+ else
+ local r = results[column]
+ r.head = head
+ r.tail = current
+ r.height = height
+ r.depth = depth
+ break
+ end
+ end
+ if not current then
+ if trace_state then
+ report_state("nilling rest")
+ end
+ rest = nil
+ elseif rest == lasthead then
+ if trace_state then
+ report_state("nilling rest as rest is lasthead")
+ end
+ rest = nil
+ end
+
+ if stripbottom then
+ local height = stripbottomglue(results,discarded)
+ if height > 0 then
+ target = height
+ end
+ end
+
+ specification.results = results
+ specification.height = target
+ specification.originalheight = originalheight
+ specification.originalwidth = originalwidth
+ specification.originalhead = originalhead
+ specification.targetheight = target or 0
+ specification.rest = rest
+ specification.overflow = overflow
+ specification.discarded = discarded
+
+ texbox[specification.box].head = nil
+
+ return specification
+end
+
+function mixedcolumns.finalize(result)
+ if result then
+ local results = result.results
+ for i=1,result.nofcolumns do
+ local r = results[i]
+ local h = r.head
+ if h then
+ h.prev = nil
+ local t = r.tail
+ if t then
+ t.next = nil
+ else
+ h.next = nil
+ r.tail = h
+ end
+ for c, list in next, r.inserts do
+ local t = { }
+ for i=1,#list do
+ local l = list[i]
+ local h = new_hlist()
+ t[i] = h
+ h.head = l.head
+ h.height = l.height
+ h.depth = l.depth
+ l.head = nil
+ end
+ t[1].prev = nil -- needs checking
+ t[#t].next = nil -- needs checking
+ r.inserts[c] = t
+ end
+ end
+ end
+ end
+end
+
+local splitruns = 0
+
+local function report_deltas(result,str)
+ local t = { }
+ for i=1,result.nofcolumns do
+ t[#t+1] = points(result.results[i].delta or 0)
+ end
+ report_state("%s, cycles: %s, deltas: %s",str,result.cycle or 1,concat(t," | "))
+end
+
+function mixedcolumns.setsplit(specification)
+ splitruns = splitruns + 1
+ if trace_state then
+ report_state("split run %s",splitruns)
+ end
+ local result = setsplit(specification)
+ if result then
+ if result.overflow then
+ if trace_state then
+ report_deltas(result,"overflow")
+ end
+ -- we might have some rest
+ elseif result.rest and specification.balance == v_yes then
+ local step = specification.step or 65536*2
+ local cycle = 1
+ local cycles = specification.cycles or 100
+ while result.rest and cycle <= cycles do
+ specification.extra = cycle * step
+ result = setsplit(specification) or result
+ if trace_state then
+ report_state("cycle: %s.%s, original height: %s, total height: %s",
+ splitruns,cycle,points(result.originalheight),points(result.nofcolumns*result.targetheight))
+ end
+ cycle = cycle + 1
+ specification.cycle = cycle
+ end
+ if cycle > cycles then
+ report_deltas(result,"too many balancing cycles")
+ elseif trace_state then
+ report_deltas(result,"balanced")
+ end
+ elseif trace_state then
+ report_deltas(result,"done")
+ end
+ return result
+ elseif trace_state then
+ report_state("no result")
+ end
+end
+
+local topskip_code = gluecodes.topskip
+local baselineskip_code = gluecodes.baselineskip
+
+function mixedcolumns.getsplit(result,n)
+ if not result then
+ report_state("flush, column: %s, no result",n)
+ return
+ end
+ local r = result.results[n]
+ if not r then
+ report_state("flush, column: %s, empty",n)
+ end
+ local h = r.head
+ if not h then
+ return new_glue(result.originalwidth)
+ end
+
+ if trace_state then
+ local id = h.id
+ if id == hlist_code then
+ report_state("flush, column: %s, top line: %s",n,nodes.toutf(h.list))
+ else
+ report_state("flush, column: %s, head node: %s",n,nodecodes[id])
+ end
+ end
+
+ h.prev = nil -- move up
+ local strutht = result.strutht
+ local strutdp = result.strutdp
+ local lineheight = strutht + strutdp
+
+ local v = new_vlist()
+ v.head = h
+
+ -- local v = vpack(h,"exactly",height)
+
+ v.width = result.originalwidth
+ if result.alternative == v_global then -- option
+ result.height = result.maxheight
+ end
+ v.height = lineheight * math.ceil(result.height/lineheight) - strutdp
+ v.depth = strutdp
+
+ for c, list in next, r.inserts do
+ -- tex.setbox("global",c,vpack(nodes.concat(list)))
+ -- tex.setbox(c,vpack(nodes.concat(list)))
+ texbox[c] = vpack(nodes.concat(list))
+ r.inserts[c] = nil
+ end
+ return v
+end
+
+function mixedcolumns.getrest(result)
+ local rest = result and result.rest
+ result.rest = nil -- to be sure
+ return rest
+end
+
+function mixedcolumns.getlist(result)
+ local originalhead = result and result.originalhead
+ result.originalhead = nil -- to be sure
+ return originalhead
+end
+
+function mixedcolumns.cleanup(result)
+ local discarded = result.discarded
+ for i=1,#discarded do
+ freenode(discarded[i])
+ end
+end
+
+-- interface --
+
+local result
+
+function commands.mixsetsplit(specification)
+ if result then
+ for k, v in next, specification do
+ result[k] = v
+ end
+ result = mixedcolumns.setsplit(result)
+ else
+ result = mixedcolumns.setsplit(specification)
+ end
+end
+
+function commands.mixgetsplit(n)
+ if result then
+ context(mixedcolumns.getsplit(result,n))
+ end
+end
+
+function commands.mixfinalize()
+ if result then
+ mixedcolumns.finalize(result)
+ end
+end
+
+function commands.mixflushrest()
+ if result then
+ context(mixedcolumns.getrest(result))
+ end
+end
+
+function commands.mixflushlist()
+ if result then
+ context(mixedcolumns.getlist(result))
+ end
+end
+
+function commands.mixstate()
+ context(result and result.rest and 1 or 0)
+end
+
+function commands.mixcleanup()
+ if result then
+ mixedcolumns.cleanup(result)
+ result = nil
+ end
+end
diff --git a/tex/context/base/page-mix.mkiv b/tex/context/base/page-mix.mkiv
new file mode 100644
index 000000000..58bc24f33
--- /dev/null
+++ b/tex/context/base/page-mix.mkiv
@@ -0,0 +1,754 @@
+%D \module
+%D [ file=page-mix,
+%D version=2012.07.12,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Mixed Columns,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Mixed Columns}
+
+%D This is a very experimental module. Eventually it will replace the current
+%D multi column mechanism (that then will be an instance). The \LUA\ part of
+%D the interface will quite probably change so don't use that one directly
+%D (yet).
+
+% todo:
+%
+% consult note class
+% notes per page
+% notes in each column
+% notes in last column
+% notes local/global
+% top and bottom inserts
+% wide floats
+% move floats
+
+% luatex buglet:
+%
+% \ctxlua{tex.setbox("global",0,node.hpack(nodes.pool.glyph("a",font.current())))}\box0
+
+\registerctxluafile{page-mix}{1.001}
+
+\unprotect
+
+%D The mixed output routine replaces the traditional multi column handler that
+%D started out in \MKII. One of the complications of a routine is that it needs
+%D to align nicely when mixed in a single column layout. Instead of using all
+%D kind of shift juggling in this mechanism we simply switch to grid mode
+%D locally. After all, columns don't look nice when not on a grid. As the grid
+%D snapper in \MKIV\ is more advanced not that much extra code is needed.
+
+%D We use the command handler but the parent settings are not to be changed.
+%D Instead we could have used a dedicated root setup, but it's not worth the
+%D trouble.
+
+\installcorenamespace{mixedcolumns}
+
+\def\s!mixedcolumn{mixedcolumn}
+
+\installframedcommandhandler \??mixedcolumns {mixedcolumns} \??mixedcolumns
+
+\setupmixedcolumns
+ [\c!distance=1.5\bodyfontsize,
+ \c!n=\plustwo,
+ %\c!rule=\v!none,
+ \c!frame=\v!off,
+ \c!strut=\v!no,
+ \c!offset=\v!overlay,
+ \c!alternative=\v!local,
+ \c!maxheight=\textheight,
+ \c!maxwidth=\makeupwidth,
+ \c!step=.25\lineheight, % needs some experimenting
+ \c!method=\ifinner\s!box\else\s!otr\fi] % automatic as suggested by WS
+
+\let\startmixedcolumns\relax % defined later
+\let\stopmixedcolumns \relax % defined later
+
+\appendtoks
+ \setuevalue{\e!start\currentmixedcolumns}{\startmixedcolumns[\currentmixedcolumns]}%
+ \setuevalue{\e!stop \currentmixedcolumns}{\stopmixedcolumns}%
+\to \everydefinemixedcolumns
+
+%D In order to avoid a mixup we use quite some local registers.
+
+\newdimen \d_page_mix_column_width
+\newdimen \d_page_mix_max_height
+\newdimen \d_page_mix_max_width
+\newdimen \d_page_mix_distance
+\newcount \c_page_mix_n_of_columns
+\newdimen \d_page_mix_threshold
+\newdimen \d_page_mix_leftskip
+\newdimen \d_page_mix_rightskip
+
+\newdimen \d_page_mix_balance_step
+\setnewconstant\c_page_mix_balance_cycles 500
+
+\setnewconstant\c_page_mix_break_forced -123
+
+\newbox \b_page_mix_preceding
+\newdimen \d_page_mix_preceding_height
+
+\newbox \b_page_mix_collected
+
+\newconstant \c_page_mix_routine
+
+\setnewconstant\c_page_mix_routine_regular \zerocount
+\setnewconstant\c_page_mix_routine_intercept\plusone
+\setnewconstant\c_page_mix_routine_continue \plustwo
+\setnewconstant\c_page_mix_routine_balance \plusthree
+\setnewconstant\c_page_mix_routine_error \plusfour
+
+%D The main environment is called as follows:
+%D
+%D \starttyping
+%D \startmixedcolumns[instance][settings]
+%D \startmixedcolumns[instance]
+%D \startmixedcolumns[settings]
+%D \stoptyping
+%D
+%D However, best is not to use this one directly but define an instance and
+%D use that one.
+
+% % For the moment only on my machine:
+%
+% \definemixedcolumns
+% [\v!columns]
+%
+% \unexpanded\def\setupcolumns
+% {\setupmixedcolumns[\v!columns]}
+
+%D In itemizations we also need columns, so let's define a apecial instance
+%D for them. These need to work well in situations like this:
+%D
+%D \starttyping
+%D \input zapf
+%D
+%D \startnarrower
+%D \startitemize[columns,two,packed][before=,after=]
+%D \dorecurse{10}{\startitem item #1 \stopitem}
+%D \stopitemize
+%D \stopnarrower
+%D
+%D \input zapf
+%D
+%D \startnarrower
+%D \startitemize[columns,two][before=,after=]
+%D \dorecurse{10}{\startitem item #1 \stopitem}
+%D \stopitemize
+%D \stopnarrower
+%D
+%D \input zapf
+%D
+%D \startnarrower
+%D \startitemize[columns,two]
+%D \dorecurse{10}{\startitem item #1 \stopitem}
+%D \stopitemize
+%D \stopnarrower
+%D
+%D \input zapf
+%D \stoptyping
+
+\ifdefined\s!itemgroupcolumns \else \def\s!itemgroupcolumns{itemgroupcolumns} \fi
+
+\definemixedcolumns
+ [\s!itemgroupcolumns]
+ [\c!n=\itemgroupparameter\c!n,
+ \c!rule=\v!off,
+ \c!balance=\v!yes]
+
+\unexpanded\def\strc_itemgroups_start_columns
+ {\startmixedcolumns[\s!itemgroupcolumns]} % we could have a fast one
+
+\unexpanded\def\strc_itemgroups_stop_columns
+ {\stopmixedcolumns}
+
+%D The mixed output routine can be in different states. First we need to intercept
+%D the already present content. This permits mixed single and multi column usage.
+%D Then we have the continuous routine, one that intercepts pages in sequence.
+%D Finally, when we finish the mixed columns mode, we can (optionally) balance the
+%D last page.
+
+\unexpanded\def\page_mix_command_routine
+ {\ifcase\c_page_mix_routine
+ \page_one_command_routine
+ \or
+ \page_mix_routine_intercept
+ \or
+ \page_mix_routine_continue
+ \or
+ \page_mix_routine_balance
+ \or
+ \page_mix_routine_error
+ \fi}
+
+%D The interceptor is quite simple, at least for the moment.
+
+\def\page_mix_routine_intercept
+ {\global\setbox\b_page_mix_preceding\vbox
+ {\page_otr_command_flush_top_insertions
+ \unvbox\normalpagebox}}
+
+%D The error routine is there but unlikely to be called. It is a left-over from
+%D the traditional routine that might come in handy some day.
+
+\def\page_mix_routine_error
+ {\showmessage\m!columns3\empty
+ \page_otr_construct_and_shipout\unvbox\normalpagebox}
+
+%D Some settings (and actions) depend on the current output routine and setting the
+%D hsize and vsize is among them. The calculation of the hsize is done elsewhere.
+
+\unexpanded\def\page_mix_command_set_hsize
+ {\hsize\d_page_mix_column_width}
+
+%D When setting the vsize we make sure that we collect a few more lines than needed
+%D so that we have enough to split over the columns. Collecting too much is somewhat
+%D tricky as they will spill over to the next page.
+
+\unexpanded\def\page_mix_command_set_vsize
+ {\vsize\dimexpr\c_page_mix_n_of_columns\textheight+\c_page_mix_n_of_columns\lineheight\relax
+ \pagegoal\vsize}
+
+%D As we use \LUA\ there is the usual amount of tracing at that end. At the tex end
+%D we only visualize boxes.
+
+\let\page_mix_hbox\hbox
+\let\page_mix_vbox\vbox
+
+\installtextracker
+ {mixedcolumns.boxes}
+ {\let\page_mix_hbox\ruledhbox
+ \let\page_mix_vbox\ruledvbox}
+ {\let\page_mix_hbox\hbox
+ \let\page_mix_vbox\vbox}
+
+%D We provide a few column break options. Interesting is that while forcing a new
+%D column in the traditional mechanism was a pain, here it works quite well.
+
+\installcolumnbreakmethod \s!mixedcolumn \v!preference
+ {\goodbreak}
+
+\installcolumnbreakmethod \s!mixedcolumn \v!yes
+ {\penalty\c_page_mix_break_forced\relax}
+
+%D As we operate in grid snapping mode, we use a dedicated macro to enable this
+%D mechamism.
+
+\def\page_mix_enable_grid_snapping
+ {\gridsnappingtrue
+ \setsystemmode\v!grid
+ \spac_grids_snap_value_set\v!yes}
+
+%D Between columns there is normally just spacing unless one enforces a rule.
+%D
+%D \starttyping
+%D \input zapf
+%D
+%D \startnarrower
+%D \startmixedcolumns[n=2,background=color,backgroundcolor=red,rulethickness=1mm,rulecolor=green,separator=rule]
+%D \input zapf
+%D \stopmixedcolumns
+%D \stopnarrower
+%D
+%D \input zapf
+%D \stoptyping
+
+\installcorenamespace{mixedcolumnsseparator}
+
+\setvalue{\??mixedcolumnsseparator\v!rule}%
+ {\starttextproperties
+ \usemixedcolumnscolorparameter\c!rulecolor
+ \vrule\!!width\mixedcolumnsparameter\c!rulethickness
+ \stoptextproperties}
+
+\unexpanded\def\page_mix_command_inject_separator
+ {\bgroup
+ \hss
+ \csname\??mixedcolumnsseparator\mixedcolumnsparameter\c!separator\endcsname
+ \hss
+ \egroup}
+
+%D We've now arrived at the real code. The start command mostly sets up the
+%D environment and variables that are used in the splitter. One of the last
+%D things happening at the start is switching over to the mixed continuous
+%D routine.
+
+\installcorenamespace{mixedcolumnsbefore}
+\installcorenamespace{mixedcolumnsstart}
+\installcorenamespace{mixedcolumnsstop}
+\installcorenamespace{mixedcolumnsafter}
+
+%D For practical reasons there is always a first argument needed that
+%D indicates the class.
+%D
+%D \starttyping
+%D \startmixedcolumns[n=3,alternative=global]
+%D \dorecurse{200}{Zomaar wat #1 met een footnote\footnote{note #1}. }
+%D \stopmixedcolumns
+%D \stoptyping
+
+\unexpanded\def\startmixedcolumns
+ {\dodoubleempty\page_mix_start_columns}
+
+\unexpanded\def\page_mix_start_columns
+ {\pushmacro\currentmixedcolumns
+ \pushmacro\currentmixedcolumnsmethod
+ \ifsecondargument
+ \singleexpandafter\page_mix_start_columns_a
+ \else\iffirstargument
+ \doubleexpandafter\page_mix_start_columns_b
+ \else
+ \doubleexpandafter\page_mix_start_columns_c
+ \fi\fi}
+
+\def\page_mix_start_columns_a[#1][#2]%
+ {\edef\currentmixedcolumns{#1}%
+ \edef\currentmixedcolumnsmethod{\mixedcolumnsparameter\c!method}%
+ \mixedcolumnsparameter\c!before\relax
+ \csname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax
+ \begingroup
+ \setupcurrentmixedcolumns[#2]%
+ \page_mix_initialize_columns
+ \csname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname}
+
+\def\page_mix_start_columns_b[#1][#2]%
+ {\doifassignmentelse{#1}%
+ {\let\currentmixedcolumns\empty
+ \page_mix_error_b}
+ {\edef\currentmixedcolumns{#1}%
+ \firstargumentfalse}%
+ \edef\currentmixedcolumnsmethod{\mixedcolumnsparameter\c!method}%
+ \mixedcolumnsparameter\c!before\relax % so, it doesn't list to local settings !
+ \csname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax
+ \begingroup
+ \iffirstargument
+ \setupcurrentmixedcolumns[#1]%
+ \fi
+ \page_mix_initialize_columns
+ \csname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname} % no \relax
+
+\def\page_mix_error_b
+ {\writestatus\m!columns{best use an instance of mixed columns}}
+
+\def\page_mix_start_columns_c[#1][#2]%
+ {\let\currentmixedcolumns\empty
+ \edef\currentmixedcolumnsmethod{\mixedcolumnsparameter\c!method}%
+ \mixedcolumnsparameter\c!before\relax
+ \csname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax
+ \begingroup
+ \page_mix_initialize_columns
+ \csname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname}
+
+\unexpanded\def\page_mix_fast_columns_start#1%
+ {\pushmacro\currentmixedcolumns
+ \pushmacro\currentmixedcolumnsmethod
+ \edef\currentmixedcolumns{#1}%
+ \edef\currentmixedcolumnsmethod{\mixedcolumnsparameter\c!method}%
+ \mixedcolumnsparameter\c!before\relax % so, it doesn't list to local settings !
+ \csname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax
+ \begingroup
+ \page_mix_initialize_columns
+ \csname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname} % no \relax
+
+%D When we stop, we switch over to the balancing routine. After we're done we
+%D make sure to set the sizes are set, a somewhat redundant action when we
+%D already have flushed but better be safe.
+
+\unexpanded\def\stopmixedcolumns
+ {\csname\??mixedcolumnsstop \currentmixedcolumnsmethod\endcsname % no \relax
+ \endgroup
+ \csname\??mixedcolumnsafter\currentmixedcolumnsmethod\endcsname\relax
+ \mixedcolumnsparameter\c!after\relax
+ \popmacro\currentmixedcolumnsmethod
+ \popmacro\currentmixedcolumns}
+
+\let\page_mix_fast_columns_stop\stopmixedcolumns
+
+%D This is how the fast one is used:
+
+\unexpanded\def\strc_itemgroups_start_columns
+ {\page_mix_fast_columns_start\s!itemgroupcolumns}
+
+\let\strc_itemgroups_stop_columns\page_mix_fast_columns_stop
+
+%D The common initialization:
+
+\def\page_mix_initialize_columns
+ {\page_mix_enable_grid_snapping
+ %
+ \holdinginserts\maxdimen
+ %
+ \d_page_mix_distance \mixedcolumnsparameter\c!distance
+ \c_page_mix_n_of_columns\mixedcolumnsparameter\c!n
+ \d_page_mix_max_height \mixedcolumnsparameter\c!maxheight
+ \d_page_mix_max_width \mixedcolumnsparameter\c!maxwidth
+ \d_page_mix_balance_step\mixedcolumnsparameter\c!step
+ %
+ \d_page_mix_max_width\dimexpr\d_page_mix_max_width-\leftskip-\rightskip\relax
+ \d_page_mix_leftskip \leftskip
+ \d_page_mix_rightskip\rightskip
+ \leftskip \zeropoint
+ \rightskip\zeropoint
+ %
+ \d_page_mix_threshold\zeropoint
+ %
+ \d_page_mix_column_width\dimexpr(\d_page_mix_max_width-\d_page_mix_distance*\numexpr(\c_page_mix_n_of_columns-\plusone)\relax)/\c_page_mix_n_of_columns\relax
+ %
+ \usemixedcolumnscolorparameter\c!color
+ %
+ \nofcolumns\c_page_mix_n_of_columns} % public
+
+%D The otr method related hooks are defined next:
+
+% \setvalue{\??mixedcolumnsbefore\s!otr}%
+% {\par
+% \ifdim\pagetotal=\zeropoint \else
+% \verticalstrut % probably no longer needed
+% \vskip-\struttotal % probably no longer needed
+% \fi}
+
+\newcount\c_page_mix_otr_nesting
+
+\setvalue{\??mixedcolumnsbefore\s!otr}%
+ {\par
+ \global\advance\c_page_mix_otr_nesting\plusone
+ \ifcase\c_page_mix_otr_nesting\or
+ \ifdim\pagetotal=\zeropoint \else
+ \obeydepth % we could handle this in pre material
+ \fi
+ \fi}
+
+\setvalue{\??mixedcolumnsstart\s!otr}%
+ {\ifcase\c_page_mix_otr_nesting\or
+ \setupoutputroutine[\s!mixedcolumn]%
+ \c_page_mix_routine\c_page_mix_routine_intercept
+ \page_otr_trigger_output_routine
+ \global\d_page_mix_preceding_height\ht\b_page_mix_preceding
+ \c_page_mix_routine\c_page_mix_routine_continue
+ %
+ \page_mix_command_set_vsize
+ \page_mix_command_set_hsize
+ \fi}
+
+\setvalue{\??mixedcolumnsstop\s!otr}%
+ {\par
+ \ifcase\c_page_mix_otr_nesting\or
+ \c_page_mix_routine\c_page_mix_routine_balance
+ \page_otr_trigger_output_routine
+ \fi}
+
+\setvalue{\??mixedcolumnsafter\s!otr}%
+ {\ifcase\c_page_mix_otr_nesting\or
+ \prevdepth\strutdp
+ \page_otr_command_set_vsize
+ \page_otr_command_set_hsize
+ \fi
+ \global\advance\c_page_mix_otr_nesting\minusone}
+
+%D The splitting and therefore balancing is done at the \LUA\ end. This gives
+%D more readable code and also makes it easier to deal with insertions like
+%D footnotes. Eventually we will have multiple strategies available.
+
+\unexpanded\def\page_mix_routine_construct#1%
+ {\ctxcommand{mixsetsplit {
+ box = \number\b_page_mix_collected,
+ nofcolumns = \number\c_page_mix_n_of_columns,
+ maxheight = \number\d_page_mix_max_height,
+ step = \number\d_page_mix_balance_step,
+ cycles = \number\c_page_mix_balance_cycles,
+ preheight = \number\d_page_mix_preceding_height,
+ prebox = \number\b_page_mix_preceding,
+ strutht = \number\strutht,
+ strutdp = \number\strutdp,
+ threshold = \number\d_page_mix_threshold,
+ balance = "#1",
+ alternative = "\mixedcolumnsparameter\c!alternative",
+ }}%
+ \deadcycles\zerocount}
+
+\unexpanded\def\page_mix_routine_package
+ {\ctxcommand{mixfinalize()}%
+ \setbox\b_page_mix_collected\vbox \bgroup
+ \ifvoid\b_page_mix_preceding \else
+ \box\b_page_mix_preceding
+ \global\d_page_mix_preceding_height\zeropoint
+ \nointerlineskip
+ \fi
+ \hskip\d_page_mix_leftskip
+ \page_mix_hbox to \d_page_mix_max_width \bgroup
+ \letmixedcolumnsparameter\c!strut\v!no
+ % maybe use \c_page_mix_used_of_columns
+ \dorecurse\c_page_mix_n_of_columns {%
+ \inheritedmixedcolumnsframed{\page_mix_command_package_column}%
+ \ifnum\recurselevel<\c_page_mix_n_of_columns
+ \page_mix_command_inject_separator
+ \fi
+ }%
+ \egroup
+ \egroup}
+
+\unexpanded\def\page_mix_command_package_column
+ {\page_mix_hbox to \d_page_mix_column_width \bgroup
+ % maybe intercept empty
+ \ctxcommand{mixgetsplit(\recurselevel)}%
+ \hskip-\d_page_mix_column_width
+ \page_mix_hbox to \d_page_mix_column_width \bgroup
+ \placenoteinserts
+ \hss
+ \egroup
+ \egroup}
+
+\unexpanded\def\page_mix_routine_continue
+ {\bgroup
+ \forgetall
+ \dontcomplain
+ \setbox\b_page_mix_collected\vbox{\unvbox\normalpagebox}% brrr we need to make a tight box (combine this in lua)
+ \page_mix_routine_construct\v!no
+ \page_mix_routine_package
+ \page_otr_construct_and_shipout\box\b_page_mix_collected
+ \ctxcommand{mixflushrest()}%
+ \ctxcommand{mixcleanup()}%
+ \egroup}
+
+\unexpanded\def\page_mix_routine_balance
+ {\bgroup
+ \forgetall
+ \dontcomplain
+ \setbox\b_page_mix_collected\vbox{\unvbox\normalpagebox}% brrr we need to make a tight box (combine this in lua)
+ \doloop
+ {%writestatus\m!columns{construct continue (\the\htdp\b_page_mix_collected)}%
+ \page_mix_routine_construct\v!no
+ \ifcase\ctxcommand{mixstate()}\relax
+ % 0 = okay, we can balance
+ \setbox\b_page_mix_collected\vbox{\ctxcommand{mixflushlist()}}% we could avoid this
+ %writestatus\m!columns{construct balance}%
+ \page_mix_routine_construct\v!yes
+ \page_mix_routine_package
+ \c_page_mix_routine\c_page_mix_routine_regular
+ % \setupoutputroutine[\s!singlecolumn]%
+ \page_otr_command_set_vsize
+ \page_otr_command_set_hsize
+ \par
+ %writestatus\m!columns{flush balance}%
+ \box\b_page_mix_collected
+ \par
+ \nointerlineskip
+ \prevdepth\strutdp
+ \ctxcommand{mixflushrest()}% rubish
+ \ctxcommand{mixcleanup()}% rubish
+ \exitloop
+ \or
+ % 1 = we have stuff left, so flush and rebalance
+ %writestatus\m!columns{flush continue}%
+ \page_mix_routine_package
+ \page_otr_construct_and_shipout\box\b_page_mix_collected
+ \setbox\b_page_mix_collected\vbox{\ctxcommand{mixflushrest()}}% we could avoid this
+ \ctxcommand{mixcleanup()}%
+ \ifdim\ht\b_page_mix_collected=\zeropoint
+ \exitloop
+ \fi
+ \fi}%
+ \egroup}
+
+%D We also implement a variant compatible with the so called simple columns
+%D mechanism:
+%D
+%D \starttyping
+%D \startboxedcolumns
+%D \input zapf
+%D \stopboxedcolumns
+%D \stoptyping
+%D
+%D This is a rather mininimalistic variant.
+
+% Maybe we also need a variant with obeydepth before and prevdepth after so
+% that we get a nice spacing.
+
+\definemixedcolumns
+ [boxedcolumns]
+ [\c!balance=\v!yes,
+ \c!n=2,
+ \c!method=\s!box,
+ \c!strut=\v!yes,
+ \c!maxwidth=\availablehsize]
+
+%D Boxed columns can be used nested:
+%D
+%D \starttyping
+%D \setupmixedcolumns
+%D [boxedcolumns]
+%D [n=2,
+%D background=color,
+%D backgroundcolor=darkred,
+%D color=white,
+%D backgroundoffset=1mm]
+%D
+%D \definemixedcolumns
+%D [nestedboxedcolumns]
+%D [boxedcolumns]
+%D [n=2,
+%D background=color,
+%D backgroundcolor=white,
+%D color=darkred,
+%D strut=yes,
+%D backgroundoffset=0mm]
+%D
+%D \startboxedcolumns
+%D \input zapf \par \input ward \par \obeydepth
+%D \startnestedboxedcolumns
+%D \input zapf
+%D \stopnestedboxedcolumns
+%D \par \input zapf \par \obeydepth
+%D \startnestedboxedcolumns
+%D \input zapf
+%D \stopnestedboxedcolumns
+%D \par \input zapf
+%D \stopboxedcolumns
+%D \stoptyping
+
+%D Next we define the hooks:
+
+\letvalue{\??mixedcolumnsbefore\s!box}\donothing
+\letvalue{\??mixedcolumnsafter \s!box}\donothing
+
+\setvalue{\??mixedcolumnsstart\s!box}%
+ {\edef\p_page_mix_strut{\mixedcolumnsparameter\c!strut}%
+ \setbox\b_page_mix_collected\vbox\bgroup
+ \let\currentoutputroutine\s!mixedcolumn % makes \column work
+ \forgetall
+ \page_mix_command_set_hsize
+ \ifx\p_page_mix_strut\v!yes
+ \begstrut
+ \ignorespaces
+ \fi}
+
+\setvalue{\??mixedcolumnsstop\s!box}%
+ {\ifx\p_page_mix_strut\v!yes
+ \removeunwantedspaces
+ \endstrut
+ \fi
+ \egroup
+ \page_mix_box_balance}
+
+%D The related balancer is only a few lines:
+
+\unexpanded\def\page_mix_box_balance
+ {\bgroup
+ \dontcomplain
+ \page_mix_routine_construct\v!yes
+ \page_mix_routine_package
+ \dontleavehmode\box\b_page_mix_collected
+ \ctxcommand{mixflushrest()}%
+ \ctxcommand{mixcleanup()}%
+ \egroup}
+
+%D As usual, floats complicates matters and this is where experimental code
+%D starts.
+
+\let\page_mix_command_package_contents\page_one_command_package_contents
+\let\page_mix_command_flush_float_box \page_one_command_flush_float_box
+
+\unexpanded\def\page_mix_command_check_if_float_fits
+ {\ifpostponecolumnfloats
+ \global\setfalse\c_page_floats_room
+ \else\ifconditional\c_page_floats_not_permitted
+ \global\setfalse\c_page_floats_room
+ \else
+% \bgroup
+% \getcolumnstatus{\count255}{\dimen0}{\dimen2}%
+% \page_floats_get_info\s!text
+% \setbox\scratchbox\vbox % tricky met objecten ?
+% {\blank[\rootfloatparameter\c!spacebefore]
+% \snaptogrid\vbox{\vskip\floatheight}}% copy?
+% \advance\dimen0\dimexpr\ht\scratchbox+2\openlineheight+.5\lineheight\relax\relax % needed because goal a bit higher
+% \ifdim\dimen0>\dimen2
+% \global\setfalse\c_page_floats_room
+% \else
+ \global\settrue\c_page_floats_room
+ \fi
+ \ifdim\floatwidth>\hsize
+ \showmessage\m!columns{11}\empty
+ \global\setfalse\c_page_floats_room
+ \fi}
+
+\unexpanded\def\page_mix_command_flush_floats
+ {\page_one_command_flush_floats}
+
+\unexpanded\def\page_mix_command_flush_saved_floats
+ {\page_one_command_flush_saved_floats}
+
+% \unexpanded\def\page_mix_command_flush_top_insertions
+% {\page_one_command_flush_top_insertions}
+
+% \unexpanded\def\page_mix_place_float_top
+% {\showmessage\m!columns4\empty\page_one_place_float_here}
+
+% \unexpanded\def\page_mix_place_float_bottom
+% {\showmessage\m!columns5\empty\page_one_place_float_here}
+
+\unexpanded\def\page_mix_place_float_here
+ {\page_one_place_float_here}
+
+\unexpanded\def\page_mix_place_float_force
+ {\page_one_place_float_force}
+
+\unexpanded\def\page_mix_command_side_float_output % hm
+ {\page_otr_construct_and_shipout\unvbox\normalpagebox}
+
+\unexpanded\def\page_mix_command_synchronize_side_floats % hm
+ {\page_sides_forget_floats}
+
+\unexpanded\def\page_mix_command_flush_side_floats
+ {\page_sides_forget_floats}
+
+\unexpanded\def\page_mix_command_next_page
+ {\page_otr_eject_page}
+
+\unexpanded\def\page_mix_command_next_page_and_inserts
+ {\page_otr_eject_page_and_flush_inserts}
+
+%D We need to hook some handlers into the output routine and we define
+%D a dedicated one:
+
+\defineoutputroutine
+ [\s!mixedcolumn]
+ [\s!page_otr_command_routine =\page_mix_command_routine,
+ \s!page_otr_command_package_contents =\page_mix_command_package_contents,
+ \s!page_otr_command_set_vsize =\page_mix_command_set_vsize,
+ \s!page_otr_command_set_hsize =\page_mix_command_set_hsize,
+ \s!page_otr_command_next_page =\page_mix_command_next_page,
+ \s!page_otr_command_next_page_and_inserts =\page_mix_command_next_page_and_inserts,
+ % \s!page_otr_command_synchronize_hsize =\page_mix_command_synchronize_hsize,
+ % \s!page_otr_command_set_top_insertions =\page_mix_command_set_top_insertions,
+ % \s!page_otr_command_set_bottom_insertions =\page_mix_command_set_bottom_insertions,
+ % \s!page_otr_command_flush_top_insertions =\page_mix_command_flush_top_insertions,
+ % \s!page_otr_command_flush_bottom_insertions=\page_mix_command_flush_bottom_insertions,
+ % \s!page_otr_command_set_float_hsize =\page_mix_command_set_float_hsize,
+ \s!page_otr_command_check_if_float_fits =\page_mix_command_check_if_float_fits,
+ \s!page_otr_command_flush_float_box =\page_mix_command_flush_float_box,
+ \s!page_otr_command_synchronize_side_floats=\page_mix_command_synchronize_side_floats,
+ \s!page_otr_command_side_float_output =\page_mix_command_side_float_output,
+ \s!page_otr_command_flush_floats =\page_mix_command_flush_floats,
+ \s!page_otr_command_flush_side_floats =\page_mix_command_flush_side_floats,
+ \s!page_otr_command_flush_saved_floats =\page_mix_command_flush_saved_floats
+ % \s!page_otr_command_flush_margin_blocks =\page_mix_command_flush_margin_blocks, % not used
+ ]
+
+%D Only a few float placement options are supported:
+
+\installfloatmethod \s!mixedcolumn \v!here \page_mix_place_float_here
+\installfloatmethod \s!mixedcolumn \v!force \page_mix_place_float_force
+\installfloatmethod \s!mixedcolumn \v!top \page_mix_place_float_top
+\installfloatmethod \s!mixedcolumn \v!bottom \page_mix_place_float_bottom
+
+\installfloatmethod \s!mixedcolumn \v!local \somelocalfloat
+
+%D It ends here.
+
+\protect \endinput
diff --git a/tex/context/base/page-mul.mkiv b/tex/context/base/page-mul.mkiv
index ba6343e6d..00075633a 100644
--- a/tex/context/base/page-mul.mkiv
+++ b/tex/context/base/page-mul.mkiv
@@ -11,45 +11,29 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
+% todo: basecolumns as parent for columns and itemize
+
% !!! there are some issues with hsize an vsize as well as flushing
% !!! floats but this module will be redone anyway
\writestatus{loading}{ConTeXt Page Macros / Simple Multi Column}
-%D This module is mostly a copy from the original multi column
-%D routine as implemented in \type {core-mul}. When the main
-%D OTR macro's were isolated in modules and column sets were
-%D introduced, this module became part of the OTR modules. As
-%D a result this module is no longer generic. It also needs
-%D an overhaul.
+%D This module is mostly a copy from the original multi column routine as
+%D implemented in \type {core-mul}. When the main OTR macro's were
+%D isolated in modules and column sets were introduced, this module became
+%D part of the OTR modules. As a result this module is no longer generic.
\unprotect
-\definesystemvariable {kl} % KoLommen
\definesystemvariable {ks} % KolomSpan
-\unexpanded\def\page_mul_command_side_float_output
- {\page_otr_construct_and_shipout\unvbox\normalpagebox}
-
-\unexpanded\def\page_mul_command_flush_side_floats
- {\page_sides_forget_floats}
-
-\unexpanded\def\page_mul_command_synchronize_side_floats
- {\page_sides_forget_floats}
-
-\unexpanded\def\page_mul_command_next_page
- {\page_otr_eject_page}
-
-\unexpanded\def\page_mul_command_next_page_and_inserts
- {\page_otr_eject_page_and_flush_inserts}
-
% check \count<insert> multiplications
%D The following macro's implement a multi||column output routine. The original
%D implementation was based on Donald Knuth's implementation, which was adapted by
%D Craig Platt to support balancing of the last page. I gradually adapted Platt's
%D version to our needs but under certain circumstances things still went wrong. I
-%D considered all calls to Platt's \type{\balancingerror} as undesirable.
+%D considered all calls to Platt's \type{\page_mul_routine_error} as undesirable.
%D
%D This completely new implementation can handle enough situations for everyday
%D documents, but is still far from perfect. While at the moment the routine doesn't
@@ -58,7 +42,7 @@
%D \startitemize[packed]
%D \item an unlimitted number of columns
%D \item ragged or not ragged bottoms
-%D \item optional balancing without \type{\balancingerrors}
+%D \item optional balancing without \type{\page_mul_routine_errors}
%D \item different \type{\baselineskips}, \type{\spacing}, \type {\topskip} and
%D \type {\maxdepth}
%D \item left- and right indentation, e.g. within lists
@@ -72,83 +56,146 @@
%D special case of multi||columns is posible but at the cost of worse float
%D handling, worse page breaking, worse etc. Complicated multi||column page handling
%D should be done in \cap{DTP}||systems anyway.
-%D
-%D There are three commands provided for entering and leaving multi||column mode and
-%D for going to the next column:
-%D
-%D \interface \type{\beginmulticolumns} \\ \\
-%D \interface \type{\endmulticolumns} \\ \\
-%D \interface \type{\ejectcolumn} \\ \\
-\def\finalcolumntextwidth {\makeupwidth}
-\def\finalcolumntextheight {\textheight}
-\def\columntextwidth {\makeupwidth}
-\def\columntextheight {\textheight}
-\def\usercolumnwidth {\textwidth}
-\def\columntextoffset {\!!zeropoint}
+\installcorenamespace {columns}
+
+\installcommandhandler \??columns {columns} \??columns
+
+%D Going to a new columns is done by means of a \type {\ejectcolumn}. The
+%D following definition does not always work.
+
+ \unexpanded\def\ejectcolumn % not good enough
+ {\goodbreak
+ \showmessage\m!columns2\empty}
-\def\fixedcolumnheight {\textheight}
-\def\betweencolumns {\hskip\bodyfontsize}
+%D The output routines plug into a more generic mechanism as can be seen at the
+%D end of this file. So, occasionally we need to define some plugin code.
-\let\setcolumnfloats \relax % in CONTEXT used for floats
-\let\flushcolumnfloats \relax % in CONTEXT used for floats
-\let\flushcolumnfloat \relax % in CONTEXT used for floats
-\let\finishcolumnbox \relax % in CONTEXT used for backgrounds
+\unexpanded\def\page_mul_place_float_top
+ {\showmessage\m!columns4\empty\page_one_place_float_here}
-%D Both macros are redefined in \CONTEXT\ when backgrounds are applied to
-%D columns. The final values are used when flushing the columns.
+\unexpanded\def\page_mul_place_float_bottom
+ {\showmessage\m!columns5\empty\page_one_place_float_here}
-%D It's more convenient to use \type {\columnwidth} instead of messing around
-%D with boxes each time.
+\unexpanded\def\page_mul_place_float_here
+ {\page_one_place_float_here}
-\newdimen\columnwidth
-\newdimen\gutterwidth
+\unexpanded\def\page_mul_place_float_force
+ {\page_one_place_float_force}
-\def\determinecolumnwidth
+\unexpanded\def\page_mul_command_side_float_output
+ {\page_otr_construct_and_shipout\unvbox\normalpagebox}
+
+\unexpanded\def\page_mul_command_flush_side_floats
+ {\page_sides_forget_floats}
+
+\unexpanded\def\page_mul_command_synchronize_side_floats
+ {\page_sides_forget_floats}
+
+\unexpanded\def\page_mul_command_next_page
+ {\page_otr_eject_page}
+
+\unexpanded\def\page_mul_command_next_page_and_inserts
+ {\page_otr_eject_page_and_flush_inserts}
+
+\let\page_mul_initialize_floats\relax
+\let\page_mul_flush_floats \relax
+\let\page_mul_flush_float \relax
+
+%D A hook:
+
+ \let\finishcolumnbox\relax
+
+%D This will change to a local one:
+
+\ifdefined\nofcolumns \else \newcount\nofcolumn \fi
+\ifdefined\mofcolumns \else \newcount\mofcolumn \fi
+
+\appendtoks
+ \nofcolumns\columnsparameter\c!n\relax
+\to \everysetupcolumns
+
+%D Columns are separated by spacing or rules or whatever suits.
+
+\installcorenamespace{columnseparators}
+
+\setvalue{\??columnseparators\v!on }{\let\page_mul_between_columns\page_mul_between_columns_rule}
+\setvalue{\??columnseparators\v!off }{\let\page_mul_between_columns\page_mul_between_columns_space}
+\setvalue{\??columnseparators }{\let\page_mul_between_columns\page_mul_between_columns_space}
+\setvalue{\??columnseparators\s!unknown}{\let\page_mul_between_columns\p_page_mul_rule}
+
+\def\page_mul_between_columns_rule
{\bgroup
- \setbox\scratchbox\hbox
- {\page_mul_command_set_hsize
- \global\columnwidth\usercolumnwidth
- \global\gutterwidth\intercolumnwidth}%
+ \starttextproperties
+ \scratchdistance\dimexpr\columnsparameter\c!distance/2\relax
+ \hskip\scratchdistance\relax
+ \vrule
+ \!!width\linewidth
+ \ifnum\bottomraggednessmode=\plustwo % baselinebottom
+ \!!depth\strutdepth
+ \fi
+ \hskip\scratchdistance\relax
+ \stoptextproperties
\egroup}
-%D Going to a new columns is done by means of a \type {\ejectcolumn}. The
-%D following definition does not always work.
+\def\page_mul_between_columns_space
+ {\hskip\columnsparameter\c!distance\relax}
-\def\ejectcolumn
- {\goodbreak
- \showmessage\m!columns2\empty}
+\let\page_mul_between_columns\page_mul_between_columns_space
-\def\balancingerror
- {\showmessage\m!columns3\empty
- \page_otr_construct_and_shipout\unvbox\normalpagebox}
+%D We declare some registers:
+
+\newdimen \d_page_mul_available_width
+\newdimen \d_page_mul_distance
+\newdimen \d_page_mul_leftskip
+\newdimen \d_page_mul_rightskip
+\newdimen \d_page_mul_offset
+\newdimen \d_page_mul_forced_height
+\newdimen \d_page_mul_used_width
+\newdimen \d_page_mul_temp
+
+\newcount \c_page_mul_balance_minimum
+\newcount \c_page_mul_n_of_lines
+
+\newbox \b_page_mul_preceding
+\newdimen \d_page_mul_preceding_height
+\newconditional\c_page_mul_preceding_present
+
+\newbox \b_page_mul_preceding_rest_of_page
-\def\page_mul_place_float_top {\showmessage\m!columns4\empty\page_one_place_float_here}
-\def\page_mul_place_float_bottom{\showmessage\m!columns5\empty\page_one_place_float_here}
-\def\page_mul_place_float_here {\page_one_place_float_here}
-\def\page_mul_place_float_force {\page_one_place_float_force}
+\newconditional\c_page_mul_reverse
-%D The local column width is available in the dimension register \type
-%D {\localcolumnwidth}, which is calculated as:
+\newconditional\c_page_mul_trace
+
+%D The next dimensions reports the final column height .. todo
+
+ \newdimen\finalcolumnheights
+ \newcount\finalcolumnlines
+
+ \newdimen\savedpagetotal % brrr
+
+ \newif\ifstretchcolumns \stretchcolumnsfalse
+ \newif\ifheightencolumns \heightencolumnsfalse
+ \newif\ifinheritcolumns \inheritcolumnsfalse
+ \newif\ifbalancecolumns %\balancecolumnstrue
+
+%D An important one:
\unexpanded\def\page_mul_command_set_hsize % beware, this one is available for use in macros
- {\setbox\scratchbox\hbox{\parindent\zeropoint\betweencolumns}%
- \intercolumnwidth\wd\scratchbox
- \localcolumnwidth\columntextwidth
- \advance\localcolumnwidth -\leftskip
- \advance\localcolumnwidth -\rightskip
- % new
- \advance\localcolumnwidth -\colleftskip
- \advance\localcolumnwidth -\colrightskip
- %
- \advance\localcolumnwidth -\nofcolumns\intercolumnwidth
- \advance\localcolumnwidth \intercolumnwidth
- \divide \localcolumnwidth \nofcolumns
- \scratchdimen\columntextoffset
- \multiply\scratchdimen \plustwo
- \advance\localcolumnwidth -\scratchdimen
- \usercolumnwidth\localcolumnwidth
- \hsize\localcolumnwidth} % we don't do it \global
+ {\setbox\scratchbox\hbox{\page_mul_between_columns}%
+ \d_page_mul_distance\wd\scratchbox
+ \d_page_mul_available_width\dimexpr
+ \makeupwidth
+ -\d_page_mul_leftskip
+ -\d_page_mul_rightskip
+ -\nofcolumns\d_page_mul_distance
+ +\d_page_mul_distance
+ \relax
+ \d_page_mul_used_width\dimexpr
+ \d_page_mul_available_width/\nofcolumns
+ -\d_page_mul_offset*\plustwo
+ \relax
+ \hsize\d_page_mul_used_width}
%D Torture test:
%D
@@ -219,122 +266,79 @@
%D in||between material, these dimensions are influenced by bodyfont switches inside
%D multi||column mode.
-\newdimen\mcscratchdimen
-\newcount\nofcolumnlines
+\setnewconstant\multicolumnlinemethod\zerocount % 0=normal 1=raw
-\setnewconstant\multicolumnlinemethod\plusone % 0: overshoot (old default), 1: tight
+\def\multicolumnovershootratio{.5} % {\ifgridsnapping0\else.5\fi}
-\def\getmulticolumnlines
- {\mcscratchdimen-\columntextoffset
- \multiply\mcscratchdimen \plustwo
- \advance\mcscratchdimen \columntextheight
- \ifdim\precolumnboxheight>\zeropoint
- \advance\mcscratchdimen -\precolumnboxheight
- \fi
- \settotalinsertionheight
- \advance\mcscratchdimen -\totalinsertionheight
- \ifcase\multicolumnlinemethod \getnoflines\mcscratchdimen
- \or \getrawnoflines\mcscratchdimen
- \else \getrawnoflines\mcscratchdimen
+\unexpanded\def\page_mul_set_n_of_lines
+ {\settotalinsertionheight
+ \d_page_mul_temp\dimexpr
+ -\d_page_mul_offset*\plustwo
+ +\textheight
+ \ifdim\d_page_mul_preceding_height>\zeropoint -\d_page_mul_preceding_height \fi
+ -\totalinsertionheight
+ \relax
+ \ifcase\multicolumnlinemethod
+ \getnoflines \d_page_mul_temp \or
+ \getrawnoflines\d_page_mul_temp \else
+ \getrawnoflines\d_page_mul_temp
\fi
% added 30/7/2004
\ifnum\layoutlines>\zerocount \ifnum\noflines>\layoutlines
\noflines\layoutlines
\fi \fi
- \nofcolumnlines\noflines}
-
-\def\multicolumnovershootratio{.5} % {\ifgridsnapping0\else.5\fi}
+ \c_page_mul_n_of_lines\noflines}
\unexpanded\def\page_mul_command_set_vsize
{\page_one_command_set_vsize % indeed?
- \getmulticolumnlines
- \mcscratchdimen\nofcolumnlines\openlineheight
- \advance\mcscratchdimen \multicolumnovershootratio\openlineheight % collect enough data
- \global\vsize\nofcolumns\mcscratchdimen
- \global\pagegoal\vsize} % let's do it only here
+ \page_mul_set_n_of_lines
+ \d_page_mul_temp\nofcolumns\dimexpr
+ \c_page_mul_n_of_lines\openlineheight
+ +\multicolumnovershootratio\openlineheight % collect enough data
+ \relax
+ \global\vsize \d_page_mul_temp
+ \global\pagegoal\d_page_mul_temp} % let's do it only here
%D It really starts here. After some checks and initializations we change the output
%D routine to continous multi||column mode. This mode handles columns that fill the
%D current and next full pages. The method used is (more or less) multiplying \type
%D {\vsize} and dividing \type {\hsize} by \type {\nofcolumns}. More on this can be
%D found in the \TeX book. We save the top of the current page in box
-%D \type{\precolumnbox}.
+%D \type {\b_page_mul_preceding}.
%D
%D We manipulate \type {\topskip} a bit, just to be shure that is has no
%D flexibility. This has te be done every time a font switch takles place, because
-%D \type{\topskip} can depend on this.
+%D \type {\topskip} can depend on this.
\newconstant\c_page_mul_routine
-\setnewconstant\c_page_mul_routine_regular \zerocount
-\setnewconstant\c_page_mul_routine_intercept \plusone
-\setnewconstant\c_page_mul_routine_continuous \plustwo
-\setnewconstant\c_page_mul_routine_balanced \plusthree
-\setnewconstant\c_page_mul_routine_error \plusfour
+\setnewconstant\c_page_mul_routine_regular \zerocount
+\setnewconstant\c_page_mul_routine_intercept \plusone
+\setnewconstant\c_page_mul_routine_continue \plustwo
+\setnewconstant\c_page_mul_routine_balance \plusthree
+\setnewconstant\c_page_mul_routine_error \plusfour
\unexpanded\def\page_mul_command_routine
{\ifcase\c_page_mul_routine
\page_one_command_routine
\or
- \interceptmulticolumnsout
+ \page_mul_routine_intercept
\or
- \continuousmulticolumnsout
+ \page_mul_routine_continue
\or
- \balancedmulticolumnsout
+ \page_mul_routine_balance
\or
- \balancingerror
+ \page_mul_routine_error
\fi}
-\def\interceptmulticolumnsout
- {\global\setbox\precolumnbox\vbox
- {\page_otr_command_flush_top_insertions\unvbox\normalpagebox}}
+\def\page_mul_routine_intercept
+ {\global\setbox\b_page_mul_preceding\vbox
+ {\page_otr_command_flush_top_insertions
+ \unvbox\normalpagebox}}
-\def\beginmulticolumns
- {\par
- \flushnotes
- \xdef\precolumndepth{\the\prevdepth}%
- \begingroup
- % new
- \leftskip1\leftskip
- \rightskip1\rightskip
- \edef\colleftskip {\the\leftskip}%
- \edef\colrightskip{\the\rightskip}%
- \leftskip\zeropoint
- \rightskip\zeropoint
- %
- %\setcolumntextwidth\relax
- %\setcolumntextheight\relax
- \widowpenalty\zerocount % is gewoon beter
- \clubpenalty \zerocount % zeker bij grids
- \page_floats_column_push_saved
- \dimen0\dimexpr\pagetotal+\parskip+\openlineheight\relax
- \ifdim\dimen0<\pagegoal
- \allowbreak
- \else
- \break % Sometimes fails
- \fi
- \appendtoks\topskip1\topskip\to\everybodyfont
- \the\everybodyfont % ugly here
- \saveinterlinespace % ugly here
- \initializecolumns\nofcolumns
- \hangafter\zerocount
- \hangindent\zeropoint
- \reseteverypar
- \ifdim\pagetotal=\zeropoint \else
- \verticalstrut
- \vskip-\struttotal
- \fi
- \global\savedpagetotal\pagetotal
- \setupoutputroutine[\s!multicolumn]%
- \c_page_mul_routine\c_page_mul_routine_intercept
- \page_otr_trigger_output_routine % no \holdinginserts=1, can make footnote disappear !
- \global\precolumnboxheight\ht\precolumnbox
- \c_page_mul_routine\c_page_mul_routine_continuous
- \setcolumnfloats
- \dohandleallcolumns{\global\setbox\currenttopcolumnbox\emptybox}%
- \checkbegincolumnfootnotes
- \page_otr_command_set_hsize
- \page_otr_command_set_vsize}
+\def\page_mul_routine_error
+ {\showmessage\m!columns3\empty
+ \page_otr_construct_and_shipout\unvbox\normalpagebox}
%D When we leave the multi||column mode, we have to process the not yet shipped out
%D part of the columns. When we don't balance, we simply force a continuous output,
@@ -345,160 +349,150 @@
%D macro's. It takes some reasoning to find out what happens and maybe I'm making
%D some mistake, but it works.
%D
-%D Voiding box \type {\precolumnbox} is sometimes necessary, e.g. when there is no
+%D Voiding box \type {\b_page_mul_preceding} is sometimes necessary, e.g. when there is no
%D text given between \type {\begin..} and \type {\end..}. The \type {\par} is
%D needed!
-\setnewconstant\multicolumnendsyncmethod\plusone % 1: old sync 2: new sync (cont-loc/project) / may fail ! ! ! !
-
-\def\endmulticolumns
- {%\par
- \ifnum\multicolumnendsyncmethod=\plustwo
- \synchronizeoutput
- \else
- % don't combine these
- \vskip\lineheight
- \vskip-\lineheight % take footnotes into account
- \fi
- \doflushcolumnfloat % added recently
- %\doflushcolumnfloats % no, since it results in wrong top floats
- \flushnotes % before start of columns
- \par
- \ifbalancecolumns
- \ifnum\multicolumnendsyncmethod=\plusone
- \c_page_mul_routine\c_page_mul_routine_continuous
- \goodbreak
- \fi
- \c_page_mul_routine\c_page_mul_routine_balanced
- \else
- \goodbreak
- \fi
- % still the multi column routine
- \page_otr_trigger_output_routine % the prevdepth is important, try e.g. toclist in
- \prevdepth\zeropoint % columns before some noncolumned text text
- %
- \c_page_mul_routine\c_page_mul_routine_regular
-% \page_otf_set_engine_output_routine{\singlecolumnout}%
-% \page_otf_set_engine_output_routine{\page_otr_triggered_output_routine}%
- %
- \ifvoid\precolumnbox\else
- \unvbox\precolumnbox
- \fi
- \global\precolumnboxheight\zeropoint
- \endgroup % here
- \nofcolumns\plusone
- \page_otr_command_set_vsize % the outer vsize (NEEDS CHECKING)
- \synchronizeoutput % new may 2004 / we need to: \pagegoal\vsize
- \checkendcolumnfootnotes
- \dosomebreak\allowbreak
- \page_floats_column_pop_saved}
-
%D Because some initializations happen three times, we defined a macro for
%D them. Erasing \type{\everypar} is needed because we don't want anything
%D to interfere.
-\def\setmulticolumnsout
+\unexpanded\def\page_mul_initialize_variables
{\reseteverypar
\dontcomplain
\settopskip
\setmaxdepth
- \topskip1\topskip
- \splittopskip\topskip
- \splitmaxdepth\maxdepth
- \boxmaxdepth\maxdepth % dangerous
- \emergencystretch\zeropoint\relax} % sometimes needed !
+ \topskip 1\topskip
+ \splittopskip \topskip
+ \splitmaxdepth \maxdepth
+ \boxmaxdepth \maxdepth % dangerous
+ \emergencystretch\zeropoint
+ \relax} % sometimes needed !
%D Flushing the page comes to pasting the columns together and appending the result
-%D to box \type {\precolumnbox}, if not void. I've seen a lot of implementations in
+%D to box \type {\b_page_mul_preceding}, if not void. I've seen a lot of implementations in
%D which some skip was put between normal text and multi||column text. When we don't
%D want this, the baselines can be messed up. I hope the seemingly complicated
%D calculation of a correction \type {\kern} is adequate to overcome this. Although
%D not watertight, spacing is taken into account and even multiple mode changes on
%D one page go well. But cross your fingers and don't blame me.
%D
-%D One of the complications of flushing out the boxes is that \type {\precolumnbox}
+%D One of the complications of flushing out the boxes is that \type {\b_page_mul_preceding}
%D needs to be \type {\unvbox}'ed, otherwise there is too less flexibility in the
%D page when using \type {\raggedbottom}. It took a lot of time before these kind of
%D problems were overcome. Using \type {\unvbox} at the wrong moment can generate
-%D \type {\balancingerror}'s.
+%D \type {\page_mul_routine_error}'s.
%D
%D One can use the macros \type {\maxcolumnheight} and \type {\maxcolumndepth} when
%D generating material between columns as well as postprocessing column lines.
-\let\maxcolumnheight=\zeropoint
-\let\maxcolumndepth =\zeropoint
+\newdimen\maxcolumnheight
+\newdimen\maxcolumndepth
\newbox\columnpagebox
-\def\setmaxcolumndimensions
- {\let\maxcolumnheight\!!zeropoint
- \let\maxcolumndepth \!!zeropoint
- \dohandleallcolumns
- {\ifdim\ht\currentcolumnbox>\maxcolumnheight
- \edef\maxcolumnheight{\the\ht\currentcolumnbox}%
- \fi
- \ifdim\dp\currentcolumnbox>\maxcolumndepth
- \edef\maxcolumndepth{\the\dp\currentcolumnbox}%
- \fi}}
+\def\page_mul_calculate_column_result_dimensions
+ {\maxcolumnheight\zeropoint
+ \maxcolumndepth \zeropoint
+ \dohandleallcolumnscs\page_mul_calculate_column_result_dimensions_step}
+
+\def\page_mul_calculate_column_result_dimensions_step
+ {\ifdim\ht\currentcolumnbox>\maxcolumnheight
+ \maxcolumnheight\ht\currentcolumnbox
+ \fi
+ \ifdim\dp\currentcolumnbox>\maxcolumndepth
+ \maxcolumndepth\dp\currentcolumnbox
+ \fi}
\setnewconstant\multicolumntopflushmethod\plusone % 0: no correction, 1: correction when topstuff, 2: correction, 3: correction++
\setnewconstant\multicolumntopalignmethod\plustwo % 0: nothing, 1: force grid, 2: follow grid
-\def\flushprecolumnboxnogrid
- {\unvbox\precolumnbox}
-
-\def\flushprecolumnboxongrid
- {\scratchdimen\savedpagetotal
- \advance\scratchdimen -\ht\precolumnbox
- \advance\scratchdimen -\dp\precolumnbox
- \advance\scratchdimen -\topskip
- \box\precolumnbox
+\def\page_mul_flush_preceding_normal
+ {\unvbox\b_page_mul_preceding}
+
+\def\page_mul_flush_preceding_ongrid
+ {\scratchdimen\dimexpr
+ \savedpagetotal
+ -\ht\d_page_mul_preceding_height
+ -\dp\d_page_mul_preceding_depth
+ -\topskip
+ \relax
+ \box\b_page_mul_preceding
\kern\scratchdimen}
-\newconditional\someprecolumncontent
+\def\page_mul_flush_packaged_columns_continued
+ {\bgroup
+ \page_mul_flush_packaged_columns_indeed
+ \box\columnpagebox
+ \egroup}
-\def\flushcolumnedpage#1%
+\def\page_mul_flush_packaged_columns_balanced
{\bgroup
- \ifvoid\precolumnbox
- \setfalse\someprecolumncontent % will be set elsewhere
+ \page_mul_flush_packaged_columns_indeed
+ % messy correction, we need to rewrite this module (newcolumns)
+ \setbox\columnpagebox\vbox
+ {\offinterlineskip
+ \scratchdimen\ht\columnpagebox
+ \advance\scratchdimen\dp\columnpagebox % we probably lost that one already
+ \box\columnpagebox
+ \vskip-\scratchdimen}%
+ \scratchdimen\noflines\openlineheight
+ \advance\scratchdimen-\openstrutdepth
+ \ifgridsnapping
+ % quick hack (at least it works with itemize)
+ \else
+ \advance\scratchdimen-\openlineheight
+ \advance\scratchdimen\topskip
+ \fi
+ \ht\columnpagebox\scratchdimen
+ \dp\columnpagebox\openstrutdepth
+ % end of mess
+ \box\columnpagebox
+ \egroup}
+
+\def\page_mul_flush_packaged_columns_indeed
+ {\ifvoid\b_page_mul_preceding
+ \setfalse\c_page_mul_preceding_present % will be set elsewhere
\else
- \settrue\someprecolumncontent
- \page_postprocessors_box\precolumnbox
+ \settrue\c_page_mul_preceding_present
+ \page_postprocessors_box\b_page_mul_preceding
\fi
\forgetall
- \setmulticolumnsout
- \setmaxcolumndimensions
+ \page_mul_initialize_variables
+ \page_mul_calculate_column_result_dimensions
+ \page_mul_postprocess_linenumbers
\dohandleallcolumns
{\page_postprocessors_column\currentcolumnbox}%
\dohandleallcolumns
{\page_marks_synchronize_column\plusone\nofcolumns\mofcolumns\currentcolumnbox}%
- \postprocesscolumns
+ \page_mul_postprocess_lines
+ \page_mul_postprocess_columns
\dohandleallcolumns
- {\global\setbox\currentcolumnbox\hbox to \localcolumnwidth
+ {\global\setbox\currentcolumnbox\hbox to \d_page_mul_used_width
{\box\currentcolumnbox}%
- \wd\currentcolumnbox\localcolumnwidth
+ \wd\currentcolumnbox\d_page_mul_used_width
\ifheightencolumns
- \ht\currentcolumnbox\fixedcolumnheight
+ \ht\currentcolumnbox\d_page_mul_forced_height
\fi}%
- \setmaxcolumndimensions
+ \page_mul_calculate_column_result_dimensions
\overlaycolumnfootnotes
\setbox\columnpagebox\vbox
- {\hbox to \finalcolumntextwidth
- {\hskip\colleftskip\relax % new, \relax needed
- \ifreversecolumns
- \@EA\dohandlerevcolumns
+ {\hbox to \makeupwidth
+ {\hskip\d_page_mul_leftskip\relax % new, \relax needed
+ \ifconditional\c_page_mul_reverse
+ \expandafter\dohandlerevcolumns
\else
- \@EA\dohandleallcolumns
+ \expandafter\dohandleallcolumns
\fi
{\finishcolumnbox
{\setbox\scratchbox\hbox
{\ifx\finishcolumnbox\relax\else\strut\fi
- \strut\box\currentcolumnbox}%
+ \box\currentcolumnbox}% hm, why strut
\anch_mark_column_box\scratchbox
\box\scratchbox}%
\hfil}%
\unskip
- \hskip\colrightskip}}% new
+ \hskip\d_page_mul_rightskip}}% new
\scratchdimen\zeropoint
\dohandleallcolumns
{\ifdim-\ht\currenttopcolumnbox<\scratchdimen
@@ -506,31 +500,31 @@
\fi
\global\setbox\currenttopcolumnbox\emptybox}%
\advance\scratchdimen \ht\columnpagebox
- \setbox\scratchbox\hbox to \columntextwidth
+ \setbox\scratchbox\hbox to \makeupwidth
{\vrule
\!!width\zeropoint
\!!height\scratchdimen
\!!depth\dp\columnpagebox
- \dostepwiserecurse2\nofcolumns1{\hfil\betweencolumns}\hfil}%
+ \dostepwiserecurse\plustwo\nofcolumns\plusone{\hfil\page_mul_between_columns}\hfil}%
\setbox\columnpagebox\hbox
{\box\columnpagebox
- \hskip-\columntextwidth
+ \hskip-\makeupwidth
\box\scratchbox}%
- \postprocesscolumnpagebox % new, acts upon \box\columnpagebox
- \ifconditional\someprecolumncontent
- \settrue\someprecolumncontent
+ \page_mul_postprocess_page
+ \ifconditional\c_page_mul_preceding_present
+ \settrue\c_page_mul_preceding_present
% next some incredible crappy code
\ifcase\multicolumntopalignmethod
- \flushprecolumnboxnogrid % not on grid
+ \page_mul_flush_preceding_normal % not on grid
\or
- \flushprecolumnboxongrid % force on grid
- \else\ifgridsnapping % somehow this junk fails in pascal
- \flushprecolumnboxongrid % obey grid settings, force on grid
+ \page_mul_flush_preceding_ongrid % force on grid
+ \else\ifgridsnapping
+ \page_mul_flush_preceding_ongrid % obey grid settings, force on grid
\else
- \flushprecolumnboxnogrid % ignore grid settings, not on grid
+ \page_mul_flush_preceding_normal % ignore grid settings, not on grid
\fi \fi
\fi
- \global\precolumnboxheight\zeropoint
+ \global\d_page_mul_preceding_height\zeropoint
\page_otr_command_set_vsize
\dosomebreak\nobreak % hm, only needed when topstuff
\ifgridsnapping
@@ -540,7 +534,7 @@
% when we run into it again
\or
% \input tufte \startcolumns \showbaselines \input tufte \stopcolumns \input tufte
- \ifconditional\someprecolumncontent
+ \ifconditional\c_page_mul_preceding_present
% \scratchdimen\topskip
% \advance\scratchdimen -\openstrutheight
% \nointerlineskip
@@ -573,29 +567,7 @@
\dp\columnpagebox\zeropoint
\global\finalcolumnheights\ht\columnpagebox
\getnoflines\finalcolumnheights
- \global\finalcolumnlines\noflines
- \ifcase#1\else
- % messy correction, we need to rewrite this module (newcolumns)
- \setbox\columnpagebox\vbox
- {\offinterlineskip
- \scratchdimen\ht\columnpagebox
- \advance\scratchdimen\dp\columnpagebox % we probably lost that one already
- \box\columnpagebox
- \vskip-\scratchdimen}%
- \scratchdimen\noflines\openlineheight
- \advance\scratchdimen-\openstrutdepth
- \ifgridsnapping
- % quick hack (at least it works with itemize)
- \else
- \advance\scratchdimen-\openlineheight
- \advance\scratchdimen\topskip
- \fi
- \ht\columnpagebox\scratchdimen
- \dp\columnpagebox\openstrutdepth
- % end of mess
- \fi
- \box\columnpagebox
- \egroup}
+ \global\finalcolumnlines\noflines}
%D In case one didn't notice, finaly \type{\finishcolumnbox} is applied to
%D all boxes. One can use these hooks for special purposes.
@@ -639,51 +611,55 @@
%D
%D {\getbuffer}
%D
-%D This feature is implemented using the reshape macros
-%D presented in \type{supp-box}.
-
-\def\postprocesscolumns
- {\ifx\postprocesscolumnline\undefined \else
- \dohandleallcolumns
- {\global\setbox\currentcolumnbox\vtop
- {\beginofshapebox
- \unvbox\currentcolumnbox
- \unskip\unskip
- \endofshapebox
- \reshapebox
- {\dimen0\ht\shapebox
- \dimen2\dp\shapebox
- \setbox\shapebox\hbox to \hsize
- {\postprocesscolumnline\shapebox}%
- \ht\shapebox\dimen0
- \dp\shapebox\dimen2
- \box\shapebox}%
- \flushshapebox
- \reseteverypar
- \parskip\zeropoint % = \forgetall
- \verticalstrut
- \vskip-\struttotal
- \vfil}}%
- \fi
- \ifx\postprocesscolumnbox\undefined \else
- \dohandleallcolumns
- {\global\setbox\currentcolumnbox\hbox
- {\postprocesscolumnbox\currentcolumnbox}}
- \fi}
-
-%D We default to doing nothing!
-
-\let\postprocesscolumnline =\undefined
-\let\postprocesscolumnbox =\undefined
-\let\postprocesscolumnpagebox=\relax
-
-%D \macros
-%D {reversecolumnstrue}
-%D
-%D We can force the macro that takes care of combining the columns, to
-%D flush them in the revere order. Of course, by default we don't reverse.
-
-\newif\ifreversecolumns
+%D This feature is implemented using the reshape macros presented
+%D in \type{supp-box}.
+
+\ifdefined\page_postprocessors_column\else\let\page_postprocessors_column\relax\fi % operates on passed box
+\ifdefined\postprocesscolumnline \else\let\postprocesscolumnline \relax\fi % operates on passed box
+\ifdefined\postprocesscolumnbox \else\let\postprocesscolumnbox \relax\fi % operates on passed box
+\ifdefined\postprocesscolumnpagebox \else\let\postprocesscolumnpagebox \relax\fi % operates on passed box
+
+\def\page_mul_postprocess_linenumbers{\ifx\page_postprocessors_column\relax\else\page_mul_postprocess_linenumbers_indeed\fi}
+\def\page_mul_postprocess_lines {\ifx\postprocesscolumnline \relax\else\page_mul_postprocess_lines_indeed \fi}
+\def\page_mul_postprocess_columns {\ifx\postprocesscolumnbox \relax\else\page_mul_postprocess_columns_indeed \fi}
+\def\page_mul_postprocess_page {\ifx\postprocesscolumnpagebox \relax\else\page_mul_postprocess_page_indeed \fi}
+
+\def\page_mul_postprocess_linenumbers_indeed
+ {\dohandleallcolumns{\page_postprocessors_column\currentcolumnbox}}
+
+\def\page_mul_postprocess_lines_indeed
+ {\dohandleallcolumnscs\page_mul_postprocess_lines_step}
+
+\def\page_mul_postprocess_lines_step % TODO: use lua solution instead
+ {\global\setbox\currentcolumnbox\vtop
+ {\beginofshapebox
+ \unvbox\currentcolumnbox
+ \unskip\unskip
+ \endofshapebox
+ \reshapebox
+ {\scratchheight\ht\shapebox
+ \scratchdepth \dp\shapebox
+ \setbox\shapebox\hbox to \hsize
+ {\postprocesscolumnline\shapebox}%
+ \ht\shapebox\scratchheight
+ \dp\shapebox\scratchdepth
+ \box\shapebox}%
+ \flushshapebox
+ \reseteverypar
+ \parskip\zeropoint % = \forgetall
+ \verticalstrut
+ \vskip-\struttotal
+ \vfil}}
+
+\def\page_mul_postprocess_columns_indeed
+ {\dohandleallcolumnscs\page_mul_postprocess_columns_step}
+
+\def\page_mul_postprocess_columns_step
+ {\global\setbox\currentcolumnbox\hbox
+ {\postprocesscolumnbox\currentcolumnbox}}
+
+\def\page_mul_postprocess_page_indeed
+ {\postprocesscolumnpagebox\columnpagebox}
%D Here comes the simple splitting routine. It's a bit longer than expected because
%D of ragging bottoms or not. This part can be a bit shorter but I suppose that I
@@ -693,46 +669,48 @@
%D First we present some auxiliary routines. Any material, like for instance floats,
%D that is already present in the boxes is preserved.
-\def\splitcolumn#1from \box#2to \dimen#3 top \box#4%
+\newdimen\d_page_mul_split_height_used
+\newdimen\d_page_mul_split_height_max
+
+\def\page_mul_split_column#1#2#3#4% copy or box
{\bgroup
\ifdim\ht#4>\zeropoint
- \dimen0\dimen#3\relax
- \dimen2\dimen0
- \advance\dimen0 -\ht#4%
- \columnfootnotecorrection{#1}{\dimen0}%
- \setbox0\vsplit#2 to \dimen0
- \global\setbox#1\vbox to \dimen2
+ \d_page_mul_split_height_used#3\relax
+ \d_page_mul_split_height_max\d_page_mul_split_height_used
+ \advance\d_page_mul_split_height_used -\ht#4%
+ \columnfootnotecorrection{#1}\d_page_mul_split_height_used
+ \setbox\scratchbox\vsplit#2 to \d_page_mul_split_height_used
+ \global\setbox#1\vbox to \d_page_mul_split_height_max
{\ifgridsnapping
- \dimen0-\openstrutheight
- \advance\dimen0 \topskip
- \vskip\dimen0\copy#4\vskip-\dimen0
+ \scratchdimen\dimexpr\topskip-\openstrutheight\relax
+ \vskip\scratchdimen
+ \copy#4%
+ \vskip-\scratchdimen
\else
\unvcopy#4%
\fi
- \fuzzysnappedbox\unvbox0
+ \fuzzysnappedbox\unvbox\scratchbox
\fakecolumnfootnotes{#1}}%
+ \else\ifcase\c_strc_notes_page_location
+ \global\setbox#1\vsplit#2 to #3%
+ \global\setbox#1\vbox
+ {\fuzzysnappedbox\unvbox{#1}}% % or \box ?
\else
- \ifcase\c_strc_notes_page_location
- \global\setbox#1\vsplit#2 to \dimen#3%
- \global\setbox#1\vbox
- {\fuzzysnappedbox\unvbox{#1}}% % or \box ?
- \else
- \columnfootnotecorrection{#1}{\dimen#3}%
- \setbox0\vsplit#2 to \dimen#3%
- \global\setbox#1\vbox to \dimen#3%
- {\fuzzysnappedbox\unvbox0
- \fakecolumnfootnotes{#1}}%
- \fi
- \fi
+ \columnfootnotecorrection{#1}{#3}%
+ \setbox\scratchbox\vsplit#2 to #3%
+ \global\setbox#1\vbox to #3%
+ {\fuzzysnappedbox\unvbox\scratchbox
+ \fakecolumnfootnotes{#1}}%
+ \fi \fi
\egroup}
-\def\splitcurrentcolumn from \box#1to \dimen#2%
- {\splitcolumn\currentcolumnbox from \box#1 to \dimen#2 top \box\currenttopcolumnbox}
+\def\page_mul_split_current_column#1#2%
+ {\page_mul_split_column\currentcolumnbox{#1}{#2}\currenttopcolumnbox}
-\def\splitfirstcolumn from \box#1to \dimen#2%
- {\splitcolumn\firstcolumnbox from \box#1 to \dimen#2 top \box\firsttopcolumnbox}
+\def\page_mul_split_first_column#1#2%
+ {\page_mul_split_column\firstcolumnbox{#1}{#2}\firsttopcolumnbox}
-\def\splitlastcolumn from \box#1to \dimen#2%
+\def\page_mul_split_last_column#1#2%
{\global\setbox\lastcolumnbox\vbox
{\unvcopy\lasttopcolumnbox
\fuzzysnappedbox\unvbox{#1}%
@@ -740,128 +718,130 @@
%D NEW: still to be documented.
-\def\fakecolumnfootnotes#1%
- {\relax
- \ifcase\c_strc_notes_page_location\else
- \ifnum#1=\lastcolumnbox
- \fakenotes
- \fi
- \fi}
-
-\def\columnfootnotecorrection#1#2%
- {\relax
- \ifcase\c_strc_notes_page_location
- % page notes
- \or
- \ifnum#1=\firstcolumnbox\relax
- \calculatetotalclevernoteheight
- \advance#2 -\totalnoteheight
- \fi
- \else
- \ifnum#1=\lastcolumnbox\relax
- \calculatetotalclevernoteheight
- \advance#2 -\totalnoteheight
- \fi
- \fi}
-
-\def\overlaycolumnfootnotes
- {\relax
- \ifcase\c_strc_notes_page_location
- % page
- \or
- \checknotepresence \ifnotespresent \page_mul_notes_flush_first_column \fi
- \or
- \checknotepresence \ifnotespresent \page_mul_notes_flush_last_column \fi
- \fi}
-
-\newbox\b_page_mul_notes
-
-\def\page_mul_notes_flush_first_column
- {\begingroup
- \setbox\b_page_mul_notes\vbox{\placenoteinserts}%
- \ifzeropt\ht\b_page_mul_notes
- % can't happen as we already checked
- \else
- \getmulticolumnlines
- \advance\nofcolumnlines \minustwo
- \scratchdimen\dimexpr\nofcolumnlines\lineheight+\topskip\relax
- \setbox\b_page_mul_notes\hbox{\lower\scratchdimen\box\b_page_mul_notes}%
- \ht\b_page_mul_notes\openstrutheight
- \dp\b_page_mul_notes\openstrutdepth
- \wd\b_page_mul_notes\zeropoint
- \scratchdimen\ht\firstcolumnbox
- \global\setbox\firstcolumnbox\vbox to \scratchdimen
- {\box\firstcolumnbox
- \vskip-\scratchdimen
- \box\b_page_mul_notes}%
- \fi
- \endgroup}
+ \def\fakecolumnfootnotes#1%
+ {\relax
+ \ifcase\c_strc_notes_page_location\else
+ \ifnum#1=\lastcolumnbox
+ \fakenotes
+ \fi
+ \fi}
+
+ \def\columnfootnotecorrection#1#2%
+ {\relax
+ \ifcase\c_strc_notes_page_location
+ % page notes
+ \or
+ \ifnum#1=\firstcolumnbox\relax
+ \calculatetotalclevernoteheight
+ \advance#2 -\totalnoteheight
+ \fi
+ \else
+ \ifnum#1=\lastcolumnbox\relax
+ \calculatetotalclevernoteheight
+ \advance#2 -\totalnoteheight
+ \fi
+ \fi}
+
+ \def\overlaycolumnfootnotes
+ {\relax
+ \ifcase\c_strc_notes_page_location
+ % page
+ \or
+ \checknotepresence \ifnotespresent \page_mul_notes_flush_first_column \fi
+ \or
+ \checknotepresence \ifnotespresent \page_mul_notes_flush_last_column \fi
+ \fi}
+
+ \newbox\b_page_mul_notes
+
+ \def\page_mul_notes_flush_first_column
+ {\begingroup
+ \setbox\b_page_mul_notes\vbox{\placenoteinserts}%
+ \ifzeropt\ht\b_page_mul_notes
+ % can't happen as we already checked
+ \else
+ \page_mul_set_n_of_lines
+ \advance\c_page_mul_n_of_lines \minustwo
+ \scratchdimen\dimexpr\c_page_mul_n_of_lines\lineheight+\topskip\relax
+ \setbox\b_page_mul_notes\hbox{\lower\scratchdimen\box\b_page_mul_notes}%
+ \ht\b_page_mul_notes\openstrutheight
+ \dp\b_page_mul_notes\openstrutdepth
+ \wd\b_page_mul_notes\zeropoint
+ \scratchdimen\ht\firstcolumnbox
+ \global\setbox\firstcolumnbox\vbox to \scratchdimen
+ {\box\firstcolumnbox
+ \vskip-\scratchdimen
+ \box\b_page_mul_notes}%
+ \fi
+ \endgroup}
-\def\page_mul_notes_flush_last_column
- {\begingroup
- \setbox\b_page_mul_notes\vbox{\placenoteinserts}%
- \ifzeropt\ht\b_page_mul_notes
- % can't happen as we already checked
- \else
- % maybe here also \getmulticolumnlines
- \scratchdimen\dimexpr\ht\firstcolumnbox-\openstrutdepth\relax % \strutdp
- \getnoflines\scratchdimen
- \advance\noflines \minustwo
- \scratchdimen\dimexpr\noflines\lineheight+\topskip\relax
- \setbox\b_page_mul_notes\hbox{\lower\scratchdimen\box\b_page_mul_notes}%
- \ht\b_page_mul_notes\openstrutheight
- \dp\b_page_mul_notes\openstrutdepth
- \wd\b_page_mul_notes\zeropoint
- \scratchdimen\ht\lastcolumnbox
- \global\setbox\lastcolumnbox\vbox to \scratchdimen
- {\box\lastcolumnbox
- \vskip-\scratchdimen
- \box\b_page_mul_notes}%
- \fi
- \endgroup}
+ \def\page_mul_notes_flush_last_column
+ {\begingroup
+ \setbox\b_page_mul_notes\vbox{\placenoteinserts}%
+ \ifzeropt\ht\b_page_mul_notes
+ % can't happen as we already checked
+ \else
+ % maybe here also \page_mul_set_n_of_lines
+ \scratchdimen\dimexpr\ht\firstcolumnbox-\openstrutdepth\relax % \strutdp
+ \getnoflines\scratchdimen
+ \advance\noflines \minustwo
+ \scratchdimen\dimexpr\noflines\lineheight+\topskip\relax
+ \setbox\b_page_mul_notes\hbox{\lower\scratchdimen\box\b_page_mul_notes}%
+ \ht\b_page_mul_notes\openstrutheight
+ \dp\b_page_mul_notes\openstrutdepth
+ \wd\b_page_mul_notes\zeropoint
+ \scratchdimen\ht\lastcolumnbox
+ \global\setbox\lastcolumnbox\vbox to \scratchdimen
+ {\box\lastcolumnbox
+ \vskip-\scratchdimen
+ \box\b_page_mul_notes}%
+ \fi
+ \endgroup}
%D Here comes the routine that splits the long box in columns. The macro \type
-%D {\flushcolumnfloats} can be used to flush either floats that were present before
+%D {\page_mul_flush_floats} can be used to flush either floats that were present before
%D the multi||column mode was entered, or floats that migrate to next columns.
%D Flushing floats is a delicate process.
-\def\continuousmulticolumnsout
+\def\page_mul_routine_continue
{\bgroup
\forgetall
- \setmulticolumnsout
-% \dimen0=\columntextheight
-% \advance\dimen0 -\precolumnboxheight
-% \settotalinsertionheight
-% \advance\dimen0 -\totalinsertionheight
-% \ifgridsnapping % evt altijd, nog testen
-% \getnoflines{\dimen0}
-% \dimen0=\noflines\openlineheight
-% \fi
- \getmulticolumnlines
- \dimen0=\nofcolumnlines\openlineheight
+ \page_mul_initialize_variables
+ % \dimen0=\makeupheight
+ % \advance\dimen0 -\d_page_mul_preceding_height
+ % \settotalinsertionheight
+ % \advance\dimen0 -\totalinsertionheight
+ % \ifgridsnapping % evt altijd, nog testen
+ % \getnoflines{\dimen0}
+ % \dimen0=\noflines\openlineheight
+ % \fi
+ \page_mul_set_n_of_lines
+ \d_page_mul_balance_target\c_page_mul_n_of_lines\openlineheight
+ \ifconditional\c_page_mul_trace
+ \writestatus\m!columns{continue: lines=\the\c_page_mul_n_of_lines, target=\the\d_page_mul_balance_target, textheight=\the\textheight}%
+ \fi
\dohandleallcolumns
- {\splitcurrentcolumn from \box\normalpagebox to \dimen0}%
- \setbox\restofpage\vbox{\unvbox\normalpagebox}%
+ {\page_mul_split_current_column\normalpagebox\d_page_mul_balance_target}%
+ \setbox\b_page_mul_preceding_rest_of_page\vbox{\unvbox\normalpagebox}%
\ifinheritcolumns
\ifcase\bottomraggednessmode
% 0 = ragged
\dohandleallcolumns
{\global\setbox\currentcolumnbox\vbox to \ht\firstcolumnbox
- {\dimen0\dp\currentcolumnbox
+ {\scratchdepth\dp\currentcolumnbox
\unvbox\currentcolumnbox
- \vskip-\dimen0
- \vskip\openstrutdepth % \strutdp
+ \vskip\dimexpr\openstrutdepth-\scratchdepth\relax
\prevdepth\openstrutdepth % \strutdp
\vfill}}%
\strc_notes_check_if_bottom_present
- \ifconditional\c_notes_bottom_present \else
- \dimen0\ht\firstcolumnbox
- \fi
+ %\ifconditional\c_notes_bottom_present \else
+ % \dimen0\ht\firstcolumnbox % ??
+ %\fi
\or
% 1 = normal
- \advance\dimen0 \maxdepth
+ \advance\d_page_mul_balance_target\maxdepth
\dohandleallcolumns
- {\global\setbox\currentcolumnbox\vbox to \dimen0
+ {\global\setbox\currentcolumnbox\vbox to \d_page_mul_balance_target
{\unvbox\currentcolumnbox}}%
\or
% 2 = baseline
@@ -869,7 +849,7 @@
\fi
\else
\dohandleallcolumns
- {\global\setbox\currentcolumnbox\vbox to \dimen0
+ {\global\setbox\currentcolumnbox\vbox to \d_page_mul_balance_target
{\ifstretchcolumns
\unvbox\currentcolumnbox
\else
@@ -877,14 +857,14 @@
\vfill
\fi}}%
\dohandleallcolumns
- {\ht\currentcolumnbox\dimen0}% redundant
+ {\ht\currentcolumnbox\d_page_mul_balance_target}% redundant
\fi
- \setbox\precolumnbox\vbox{\flushcolumnedpage\zerocount}%
- \page_otr_construct_and_shipout\box\precolumnbox
+ \setbox\b_page_mul_preceding\vbox{\page_mul_flush_packaged_columns_continued}%
+ \page_otr_construct_and_shipout\box\b_page_mul_preceding
\page_otr_command_set_hsize
\page_otr_command_set_vsize
- \flushcolumnfloats
- \unvbox\restofpage
+ \page_mul_flush_floats
+ \unvbox\b_page_mul_preceding_rest_of_page
% \penalty\outputpenalty % gaat gruwelijk mis in opsommingen
\egroup}
@@ -894,161 +874,184 @@
%D balance columns with few lines. The use of \type {\box2} and \type {\box4}
%D garantees a more robust check when skips are used.
-\def\multicolumnsbalancemax{250} % 100 is too small when floats are involved
-
-\def\balancedmulticolumnsout
+\newbox \b_page_mul_balance_content
+\newbox \b_page_mul_balance_first_column
+\newbox \b_page_mul_balance_column
+\newconstant \c_page_mul_balance_tries_max
+\newcount \c_page_mul_balance_tries
+\newdimen \d_page_mul_balance_target
+\newdimen \d_page_mul_balance_target_less
+\newdimen \d_page_mul_balance_natural_height
+\newdimen \d_page_mul_balance_regular_height
+\newdimen \d_page_mul_balance_step
+\newdimen \d_page_mul_balance_fuzzyness
+\newdimen \d_page_mul_balance_threshold
+\newconditional\c_page_mul_balance_possible
+
+\c_page_mul_balance_tries_max 250 % 100 is too small when floats are involved
+
+\def\page_mul_routine_balance
{\bgroup
- \setmulticolumnsout
+ \page_mul_initialize_variables
\widowpenalty\zerocount
- \setbox0\vbox{\unvbox\normalpagebox}%
- \ifdim\ht0>\openlineheight % at least one line
- \ifnum\minbalancetoplines<2 % balance anyway
- \donetrue
+ \setbox\b_page_mul_balance_content\vbox{\unvbox\normalpagebox}%
+ \ifdim\ht\b_page_mul_balance_content>\openlineheight % at least one line
+ \ifnum\c_page_mul_balance_minimum<\plustwo % balance anyway
+ \settrue\c_page_mul_balance_possible
\else % check criterium to available lines
- \getnoflines{\ht0}%
+ \getnoflines{\ht\b_page_mul_balance_content}%
\divide\noflines \nofcolumns \relax
- \ifnum\noflines<\minbalancetoplines \relax
- % let's play safe
- \ifdim\dimexpr\ht0+\ht\firsttopcolumnbox+\openlineheight\relax>\columntextheight
- \donetrue % column exceeding text height
+ \ifnum\noflines<\c_page_mul_balance_minimum \relax
+ \ifdim\dimexpr\ht\b_page_mul_balance_content+\ht\firsttopcolumnbox+\openlineheight\relax>\makeupheight
+ \settrue\c_page_mul_balance_possible % column exceeding text height
\else
- \donefalse % it seems to fit
+ \setfalse\c_page_mul_balance_possible % it seems to fit
\fi
- \else % balance indeed
- \donetrue
+ \else
+ \settrue\c_page_mul_balance_possible % balance indeed
\fi
\fi
- \else % balancing does not make sense
- \donefalse
+ \else
+ \setfalse\c_page_mul_balance_possible % balancing does not make sense
\fi
- \ifdone % start balancing, was: \ifdim\ht0>\openlineheight
- \dimen0\ht0
- \advance\dimen0 \topskip
- \advance\dimen0 -\baselineskip
- \dohandleallcolumns
- {\advance\dimen0 \ht\currenttopcolumnbox}%
- \divide\dimen0 \nofcolumns
- \vbadness\plustenthousand
- \count255=\zerocount
- \bgroup
- \ifgridsnapping
- \dimen2\lineheight
- \else
- \dimen2=\onepoint % RUBISH
- \dimen2=\spacingfactor\dimen2
- \fi
- \doloop
- {\advance\count255 \plusone
- \global\setbox\restofpage\copy0\relax
- \splitfirstcolumn from \box\restofpage to \dimen0
- \dohandlemidcolumns
- {\splitcurrentcolumn from \box\restofpage to \dimen0}%
- \splitlastcolumn from \box\restofpage to \dimen0
- \setbox2\vbox{\unvcopy\firstcolumnbox}%
- \dimen4\zeropoint
- \dohandleallcolumns
- {\setbox4\vbox
- {\unvcopy\currentcolumnbox
- %rather new, test this on pdftex-z.tex
- \unpenalty\unskip\unpenalty\unskip}% maybe better in main splitter
- %\writestatus{balance}{\the\currentcolumnbox: \the\ht4}%
-% \dimen6\ht4 \ifdim\dimen6>\dimen4 \dimen4=\dimen6 \fi}%
- \ifdim\ht4>\dimen4 \dimen4=\ht4 \fi}%
- \advance\dimen4 -.0005pt % get rid of accurracy problem, pretty new
- \ifnum\count255>\multicolumnsbalancemax\relax
- \exitloop
- \else\ifdim\dimen4>\ht2
- \advance\dimen0 \dimen2\relax
- \else
- \exitloop
- \fi\fi}%
- \dohandleallcolumns
- {\global\setbox\currentcolumnbox\vbox{\unvcopy\currentcolumnbox}}% NIEUW
- \ifnum\count255>\multicolumnsbalancemax\relax
- \showmessage\m!columns7\empty
- \else
- \showmessage\m!columns8{\the\count255\space}%
- \fi
- \egroup
+ \ifconditional\c_page_mul_balance_possible % start balancing, was: \ifdim\ht\b_page_mul_balance_content>\openlineheight
+ \page_mul_balance_try_one
\ifinheritcolumns
- % We cannot assume that the first column is the tallest, if
- % only because we may have an aborted balance (one line in the
- % first column and a graphic in the second one).
- %
- % \dimen0\ht\firstcolumnbox
- % \dimen2\ht\firstcolumnbox
- %
- \dimen0=\zeropoint
- \dohandleallcolumns
- {\ifdim\ht\currentcolumnbox>\dimen0
- \dimen0=\ht\currentcolumnbox
- \fi}%
- \dimen2\dimen0
- % so far
- \advance\dimen2 -\openlineheight
- \dohandleallcolumns
- {\dimen4\ht\currentcolumnbox
- \dimen6=10\openlineheight % funny value
- \global\setbox\currentcolumnbox\vbox to \dimen0
- {\unvbox\currentcolumnbox
- \ifdim\dimen4>\dimen6
- \ifdim\dimen4<\dimen0
- \ifdim\dimen4>\dimen2
- \vskip\zeropoint % !!
- \else
- \vskip\openlineheight
- \vfill
- \fi
- \else
- \vskip\zeropoint
- \fi
- \else
- \vskip\openlineheight
- \vfill
- \fi}}%
+ \page_mul_balance_try_two
\else
- \bgroup
- \ifstretchcolumns
- \dimen0\ht\firstcolumnbox
- \dimen2=\bottomtolerance\ht\firstcolumnbox
- \setbox0\vbox{\unvcopy\lastcolumnbox}%
- \advance\dimen0 -\ht0\relax
- \advance\dimen0 -\dp0\relax
- \ifdim\dimen0>\openlineheight\relax
- \ifdim\dimen0>\dimen2\relax
- % \stretchcolumnsfalse % beter goed slecht dan slecht goed
- \showmessage\m!columns9\empty
- \fi
- \fi
- \fi
- \dohandleallcolumns
- {\global\setbox\currentcolumnbox\vbox to \ht\firstcolumnbox
- {\ifstretchcolumns
- \unvbox\currentcolumnbox
- \else
- \box\currentcolumnbox
- \vfill
- \fi}}%
- \egroup
+ \page_mul_balance_try_three
\fi
\else
% a one liner is not properly handled here, so best rewrite the text then
\showmessage\m!columns{10}\empty
- \global\setbox\firstcolumnbox\vbox{\unvbox0}%
+ \global\setbox\firstcolumnbox\vbox{\unvbox\b_page_mul_balance_content}%
\fi
\c_page_mul_routine\c_page_mul_routine_error
\baselinebottom % forces depth in separation rule
- \flushcolumnedpage\plusone
- \multicolumnseject
+ \page_mul_flush_packaged_columns_balanced
+ \page_mul_eject_page
\egroup}
-\def\multicolumnseject
+\def\page_mul_eject_page
{%\ifdim\pagetotal>\textheight
% \page_otr_trigger_output_routine % new, but wrong as fails on mixed-001.tex (wrong pagetotal at this point)
%\else
\allowbreak
}%\fi}
+\def\page_mul_balance_try_one
+ {\d_page_mul_balance_target\dimexpr\ht\b_page_mul_balance_content+\topskip-\baselineskip\relax
+ \dohandleallcolumns
+ {\advance\d_page_mul_balance_target \ht\currenttopcolumnbox}%
+ \divide\d_page_mul_balance_target \nofcolumns
+ \vbadness\plustenthousand
+ \c_page_mul_balance_tries\zerocount
+ \bgroup
+ \ifgridsnapping
+ \d_page_mul_balance_step\lineheight
+ \else
+ \d_page_mul_balance_step\spacingfactor\onepoint % rubish
+ \fi
+ \doloop\page_mul_balance_try_one_attempt
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\vbox{\unvcopy\currentcolumnbox}}%
+ \ifnum\c_page_mul_balance_tries>\c_page_mul_balance_tries_max\relax
+ \showmessage\m!columns7\empty
+ \else
+ \showmessage\m!columns8{\the\c_page_mul_balance_tries\space}%
+ \fi
+ \egroup}
+
+\def\page_mul_balance_try_one_attempt
+ {\advance\c_page_mul_balance_tries \plusone
+ \global\setbox\b_page_mul_preceding_rest_of_page\copy\b_page_mul_balance_content\relax
+ \page_mul_split_first_column\b_page_mul_preceding_rest_of_page\d_page_mul_balance_target
+ \dohandlemidcolumns
+ {\page_mul_split_current_column\b_page_mul_preceding_rest_of_page\d_page_mul_balance_target}%
+ \page_mul_split_last_column\b_page_mul_preceding_rest_of_page\d_page_mul_balance_target
+ \setbox\b_page_mul_balance_first_column\vbox{\unvcopy\firstcolumnbox}%
+ \d_page_mul_balance_natural_height\zeropoint
+ \dohandleallcolumns\page_mul_balance_try_one_attempt_step
+ \advance\d_page_mul_balance_natural_height -.0005pt % (33sp) get rid of accurracy problem, pretty new
+ \ifnum\c_page_mul_balance_tries>\c_page_mul_balance_tries_max\relax
+ \exitloop
+ \else\ifdim\d_page_mul_balance_natural_height>\ht\b_page_mul_balance_first_column
+ \advance\d_page_mul_balance_target \d_page_mul_balance_step\relax
+ \else
+ \exitloop
+ \fi\fi}
+
+\def\page_mul_balance_try_one_attempt_step
+ {\setbox\b_page_mul_balance_column\vbox
+ {\unvcopy\currentcolumnbox
+ \unpenalty
+ \unskip
+ \unpenalty
+ \unskip}% maybe better in main splitter
+ \ifdim\ht\b_page_mul_balance_column>\d_page_mul_balance_natural_height
+ \d_page_mul_balance_natural_height\ht\b_page_mul_balance_column
+ \fi}
+
+% We cannot assume that the first column is the tallest, if only because we may
+% have an aborted balance (one line in the first column and a graphic in the
+% second one).
+
+\def\page_mul_balance_try_two
+ {\d_page_mul_balance_target\zeropoint
+ \dohandleallcolumns
+ {\ifdim\ht\currentcolumnbox>\d_page_mul_balance_target
+ \d_page_mul_balance_target\ht\currentcolumnbox
+ \fi}%
+ \d_page_mul_balance_target_less\dimexpr\d_page_mul_balance_target-\openlineheight\relax
+ \dohandleallcolumnscs\page_mul_balance_try_two_step}
+
+\def\page_mul_balance_try_two_step
+ {\d_page_mul_balance_regular_height\ht\currentcolumnbox
+ \d_page_mul_balance_threshold\plusten\openlineheight % funny value
+ \global\setbox\currentcolumnbox\vbox to \d_page_mul_balance_target
+ {\unvbox\currentcolumnbox
+ \ifdim\d_page_mul_balance_regular_height>\d_page_mul_balance_threshold
+ \ifdim\d_page_mul_balance_regular_height<\d_page_mul_balance_target
+ \ifdim\d_page_mul_balance_regular_height>\d_page_mul_balance_target_less
+ \vskip\zeropoint % !!
+ \else
+ \vskip\openlineheight
+ \vfill
+ \fi
+ \else
+ \vskip\zeropoint
+ \fi
+ \else
+ \vskip\openlineheight
+ \vfill
+ \fi}}
+
+\def\page_mul_balance_try_three
+ {\bgroup
+ \ifstretchcolumns
+ \d_page_mul_balance_target\ht\firstcolumnbox
+ \d_page_mul_balance_fuzzyness\bottomtolerance\ht\firstcolumnbox
+ \setbox\b_page_mul_balance_content\vbox{\unvcopy\lastcolumnbox}%
+ \advance\d_page_mul_balance_target-\htdp\b_page_mul_balance_content\relax
+ \ifdim\d_page_mul_balance_target>\openlineheight\relax
+ \ifdim\d_page_mul_balance_target>\d_page_mul_balance_fuzzyness\relax
+ % \stretchcolumnsfalse % beter good bad than bad good
+ \showmessage\m!columns9\empty
+ \fi
+ \fi
+ \fi
+ \dohandleallcolumnscs\page_mul_balance_try_three_step
+ \egroup}
+
+\def\page_mul_balance_try_three_step
+ {\global\setbox\currentcolumnbox\vbox to \ht\firstcolumnbox
+ {\ifstretchcolumns
+ \unvbox\currentcolumnbox
+ \else
+ \box\currentcolumnbox
+ \vfill
+ \fi}}
+
%D The multicolumn mechanism is incorporated in a \CONTEXT\ interface,
%D which acts like:
%D
@@ -1105,7 +1108,7 @@
%
% \let\page_floats_column_pop_saved\relax
-% \def\setcolumnfloats % messy as it adapts everypar
+% \def\page_mul_initialize_floats % messy as it adapts everypar
% {\xdef\globalsavednoffloats{\the\savednoffloats}%
% \ifnum\globalsavednoffloats>\zerocount
% \setglobalcolumnfloats % hm, we always push so this never happens
@@ -1113,66 +1116,66 @@
% \setlocalcolumnfloats
% \fi}
-\def\setcolumnfloats % messy as it adapts everypar, we need to adapt this
- {\setlocalcolumnfloats}
-
-\newconditional\onlylocalcolumnfloats % temp hack as we will redo floats (grid snapping is also messy now)
-
-\unexpanded\def\page_mul_command_flush_floats
- {\ifconditional\onlylocalcolumnfloats
- \doflushcolumnfloats
- \else
- \page_one_command_flush_floats
- \fi}
+ \def\page_mul_initialize_floats % messy as it adapts everypar, we need to adapt this
+ {\setlocalcolumnfloats}
-\unexpanded\def\page_mul_command_check_if_float_fits
- {\ifconditional\onlylocalcolumnfloats
- \docolumnroomfloat
- \fi}
+ \newconditional\onlylocalcolumnfloats % temp hack as we will redo floats (grid snapping is also messy now)
+ \newtoks \everylocalcolumnfloatspar
-\unexpanded\def\page_mul_command_flush_saved_floats
- {\ifconditional\onlylocalcolumnfloats\relax
- \else
- \page_one_command_flush_saved_floats
- \fi}
-
-\unexpanded\def\page_mul_command_flush_top_insertions
- {\ifconditional\onlylocalcolumnfloats\relax
- \else
- \page_one_command_flush_top_insertions
- \fi}
-
-\newtoks\everylocalcolumnfloatspar
-
-\everylocalcolumnfloatspar
- {\flushnotes
- \flushcolumnfloat
- % \flushmargincontents
- \checkindentation}
+ \unexpanded\def\page_mul_command_flush_floats
+ {\ifconditional\onlylocalcolumnfloats
+ \doflushcolumnfloats
+ \else
+ \page_one_command_flush_floats
+ \fi}
-\def\setlocalcolumnfloats
- {\settrue\onlylocalcolumnfloats
- \everypar\everylocalcolumnfloatspar
- \let\flushcolumnfloat\doflushcolumnfloat
- \let\flushcolumnfloats\doflushcolumnfloats}
+ \unexpanded\def\page_mul_command_check_if_float_fits
+ {\ifconditional\onlylocalcolumnfloats
+ \docolumnroomfloat
+ \fi}
-\def\setglobalcolumnfloats
- {\setfalse\onlylocalcolumnfloats
- \reseteverypar
- \let\flushcolumnfloat\relax
- \let\flushcolumnfloats\noflushcolumnfloats}
+ \unexpanded\def\page_mul_command_flush_saved_floats
+ {\ifconditional\onlylocalcolumnfloats\relax
+ \else
+ \page_one_command_flush_saved_floats
+ \fi}
-\def\noflushcolumnfloats
- {\bgroup
- \xdef\localsavednoffloats{\the\savednoffloats}%
- \global\savednoffloats\globalsavednoffloats
- \page_otr_command_flush_top_insertions
- \xdef\globalsavenoffloats{\the\savednoffloats}%
- \ifnum\globalsavednoffloats=\zerocount
- \setlocalcolumnfloats
- \fi
- \global\savednoffloats\localsavednoffloats
- \egroup}
+ \unexpanded\def\page_mul_command_flush_top_insertions
+ {\ifconditional\onlylocalcolumnfloats\relax
+ \else
+ \page_one_command_flush_top_insertions
+ \fi}
+
+ \appendtoks
+ \flushnotes
+ \page_mul_flush_float
+ %\flushmargincontents
+ \checkindentation
+ \to \everylocalcolumnfloatspar
+
+ \def\setlocalcolumnfloats
+ {\settrue\onlylocalcolumnfloats
+ \everypar\everylocalcolumnfloatspar
+ \let\page_mul_flush_float\doflushcolumnfloat
+ \let\page_mul_flush_floats\doflushcolumnfloats}
+
+ \def\setglobalcolumnfloats
+ {\setfalse\onlylocalcolumnfloats
+ \reseteverypar
+ \let\page_mul_flush_float\relax
+ \let\page_mul_flush_floats\noflushcolumnfloats}
+
+ \def\noflushcolumnfloats
+ {\bgroup
+ \xdef\localsavednoffloats{\the\savednoffloats}%
+ \global\savednoffloats\globalsavednoffloats
+ \page_otr_command_flush_top_insertions
+ \xdef\globalsavenoffloats{\the\savednoffloats}%
+ \ifnum\globalsavednoffloats=\zerocount
+ \setlocalcolumnfloats
+ \fi
+ \global\savednoffloats\localsavednoffloats
+ \egroup}
%D We need to calculate the amount of free space in a columns. When there is not
%D enough room, we migrate the float to the next column. These macro's are
@@ -1181,124 +1184,124 @@
%D floats have to be taken into account when we calculate the available space. It's
%D a pitty that such things are no integral part of \TEX.
-\def\getcolumnstatus\column#1\total#2\goal#3\\%
- {\dimen0=\ifdim\pagegoal<\maxdimen \pagetotal \else \zeropoint \fi
- \dimen2=\zeropoint
- \count255=\zerocount
- \dimen8=\columntextheight
- \advance\dimen8 -\precolumnboxheight
- \def\dogetcolumnstatus
- {\advance\count255 \plusone
- \advance\dimen2 \ht\currenttopcolumnbox
- \advance\dimen2 \dp\currenttopcolumnbox
- \dimen4\dimen2
- \advance\dimen4 \dimen0
- \dimen6=\count255\dimen8
- \ifdim\dimen4>\dimen6
- \else
- \let\dogetcolumnstatus\relax
- \fi}%
- \dohandleallcolumns{\dogetcolumnstatus}%
- \ifnum\count255=0 \count255=1 \fi
- #1=\count255
- #2=\dimen4
- #3=\dimen6 }
-
-\def\getinsertionheight
- {\ifdim\pagegoal<\maxdimen
- \bgroup
- \dimen0=\columntextheight
- \advance\dimen0 -\pagegoal
- \xdef\insertionheight{\the\dimen0}%
- \egroup
- \else
- \global\let\insertionheight\zeropoint
- \fi}
-
-\def\docolumnroomfloat
- {\ifpostponecolumnfloats
- \global\setfalse\c_page_floats_room
- \else\ifconditional\c_page_floats_not_permitted
- \global\setfalse\c_page_floats_room
- \else
- \bgroup
- \getcolumnstatus\column\count255\total\dimen0\goal\dimen2\\%
- \page_floats_get_info\s!text
- \setbox\scratchbox\vbox % tricky met objecten ?
- {\blank[\rootfloatparameter\c!spacebefore]
- \snaptogrid\vbox{\vskip\floatheight}}% copy?
- \advance\dimen0\dimexpr\ht\scratchbox+2\openlineheight+.5\lineheight\relax\relax % needed because goal a bit higher
- \ifdim\dimen0>\dimen2
- \global\setfalse\c_page_floats_room
- \else
- \global\settrue\c_page_floats_room
- \fi
- \ifdim\floatwidth>\hsize
- \showmessage\m!columns{11}\empty
- \global\setfalse\c_page_floats_room
- \fi
- \egroup
- \fi\fi}
+ \def\getcolumnstatus#1#2#3%
+ {\dimen0=\ifdim\pagegoal<\maxdimen \pagetotal \else \zeropoint \fi
+ \dimen2=\zeropoint
+ \count255=\zerocount
+ \dimen8=\makeupheight
+ \advance\dimen8 -\d_page_mul_preceding_height
+ \def\dogetcolumnstatus
+ {\advance\count255 \plusone
+ \advance\dimen2 \ht\currenttopcolumnbox
+ \advance\dimen2 \dp\currenttopcolumnbox
+ \dimen4\dimen2
+ \advance\dimen4 \dimen0
+ \dimen6=\count255\dimen8
+ \ifdim\dimen4>\dimen6
+ \else
+ \let\dogetcolumnstatus\relax
+ \fi}%
+ \dohandleallcolumns{\dogetcolumnstatus}%
+ \ifnum\count255=0 \count255=1 \fi
+ #1=\count255
+ #2=\dimen4
+ #3=\dimen6 }
+
+ \def\getinsertionheight
+ {\ifdim\pagegoal<\maxdimen
+ \bgroup
+ \dimen0=\makeupheight
+ \advance\dimen0 -\pagegoal
+ \xdef\insertionheight{\the\dimen0}%
+ \egroup
+ \else
+ \global\let\insertionheight\zeropoint
+ \fi}
+
+ \def\docolumnroomfloat
+ {\ifpostponecolumnfloats
+ \global\setfalse\c_page_floats_room
+ \else\ifconditional\c_page_floats_not_permitted
+ \global\setfalse\c_page_floats_room
+ \else
+ \bgroup
+ \getcolumnstatus{\count255}{\dimen0}{\dimen2}%
+ \page_floats_get_info\s!text
+ \setbox\scratchbox\vbox % tricky met objecten ?
+ {\blank[\rootfloatparameter\c!spacebefore]
+ \snaptogrid\vbox{\vskip\floatheight}}% copy?
+ \advance\dimen0\dimexpr\ht\scratchbox+2\openlineheight+.5\lineheight\relax\relax % needed because goal a bit higher
+ \ifdim\dimen0>\dimen2
+ \global\setfalse\c_page_floats_room
+ \else
+ \global\settrue\c_page_floats_room
+ \fi
+ \ifdim\floatwidth>\hsize
+ \showmessage\m!columns{11}\empty
+ \global\setfalse\c_page_floats_room
+ \fi
+ \egroup
+ \fi\fi}
%D Flushing one float is done as soon as possible, i.e. \type {\everypar}.
%D This means that (at the moment) sidefloats are not supported (overulled)!
-\newif\ifflushingcolumnfloats \flushingcolumnfloatstrue
-
-\def\doflushcolumnfloat
- {\ifpostponecolumnfloats\else\ifflushingcolumnfloats\ifconditional\c_page_floats_some_waiting
- \doflushcolumnfloatindeed
- \fi\fi\fi}
-
-\def\doflushcolumnfloatindeed
- {\bgroup
- \forgetall
- \let\doflushcolumnfloat\relax
- \getcolumnstatus\column\mofcolumns\total\dimen0\goal\dimen2\\%
- \ifdim\dimen0>\zeropoint
- \page_floats_get_info\s!text
- \ifdim\floatwidth>\hsize
- % dropped ?
- \else
- \setbox2\vbox
- {\blank[\rootfloatparameter\c!spacebefore]
- \snaptogrid\vbox{\vskip\floatheight}}%
- \advance\dimen0 \ht2
- \ifdim\dimen0>\dimen2
- \ifnum\mofcolumns<\nofcolumns
- \advance\mofcolumns \plusone
- \ifdim\ht\currenttopcolumnbox=\zeropoint
- \page_floats_flush\s!text\plusone
- \global\setbox\currenttopcolumnbox\vbox
- {\snaptogrid\vbox{\box\floatbox}
- \whitespace % nodig ?
- \blank[\rootfloatparameter\c!spaceafter]}%
- \dimen4=\htdp\currenttopcolumnbox
- \global\advance\vsize -\dimen4
- \advance\dimen4 -\pagegoal
- \global\pagegoal-\dimen4
- \showmessage\m!columns{12}a%
+ \newif\ifflushingcolumnfloats \flushingcolumnfloatstrue
+
+ \def\doflushcolumnfloat
+ {\ifpostponecolumnfloats\else\ifflushingcolumnfloats\ifconditional\c_page_floats_some_waiting
+ \doflushcolumnfloatindeed
+ \fi\fi\fi}
+
+ \def\doflushcolumnfloatindeed
+ {\bgroup
+ \forgetall
+ \let\doflushcolumnfloat\relax
+ \getcolumnstatus{\mofcolumns}{\dimen0}{\dimen2}%
+ \ifdim\dimen0>\zeropoint
+ \page_floats_get_info\s!text
+ \ifdim\floatwidth>\hsize
+ % dropped ?
+ \else
+ \setbox2\vbox
+ {\blank[\rootfloatparameter\c!spacebefore]
+ \snaptogrid\vbox{\vskip\floatheight}}%
+ \advance\dimen0 \ht2
+ \ifdim\dimen0>\dimen2
+ \ifnum\mofcolumns<\nofcolumns
+ \advance\mofcolumns \plusone
+ \ifdim\ht\currenttopcolumnbox=\zeropoint
+ \page_floats_flush\s!text\plusone
+ \global\setbox\currenttopcolumnbox\vbox
+ {\snaptogrid\vbox{\box\floatbox}
+ \whitespace % nodig ?
+ \blank[\rootfloatparameter\c!spaceafter]}%
+ \dimen4=\htdp\currenttopcolumnbox
+ \global\advance\vsize -\dimen4
+ \advance\dimen4 -\pagegoal
+ \global\pagegoal-\dimen4
+ \showmessage\m!columns{12}a%
+ \else
+ \showmessage\m!columns{12}b%
+ \fi
+ \else
+ \showmessage\m!columns{12}c%
+ \fi
\else
- \showmessage\m!columns{12}b%
+ \ifhmode{\setbox0\lastbox}\fi% waar is die er in geslopen
+ \par
+ \ifdim\prevdepth<\zeropoint \else % anders bovenaan kolom witruimte
+ \nobreak
+ \blank[\rootfloatparameter\c!spacebefore]
+ \nobreak
+ \fi
+ \page_floats_flush\s!text\plusone
+ \page_otr_command_flush_float_box
+ \blank[\rootfloatparameter\c!spaceafter]
\fi
- \else
- \showmessage\m!columns{12}c%
\fi
- \else
- \ifhmode{\setbox0\lastbox}\fi% waar is die er in geslopen
- \par
- \ifdim\prevdepth<\zeropoint \else % anders bovenaan kolom witruimte
- \nobreak
- \blank[\rootfloatparameter\c!spacebefore]
- \nobreak
- \fi
- \page_floats_flush\s!text\plusone
- \page_otr_command_flush_float_box
- \blank[\rootfloatparameter\c!spaceafter]
\fi
- \fi
- \fi
- \egroup}
+ \egroup}
%D This one looks complicated. Upto \type{\nofcolumns} floats are placed,
%D taking the width of a float into account. This routine can be improved
@@ -1313,96 +1316,96 @@
%D When handling lots of (small) floats spacing can get worse because of
%D lining out the columns.
-\def\doflushcolumnfloats
- {\ifpostponecolumnfloats\else
- \bgroup
- \forgetall
- \ifconditional\c_page_floats_some_waiting
- \dimen8\zeropoint
- \dimen4\zeropoint
- \count0\zerocount % count0 can be used local
- \count2\nofcolumns % count2 can be used local
- \dohandleallcolumns
- {\ifnum\count0>\zerocount % the wide one's reserved space
- \global\setbox\currenttopcolumnbox\vbox
- {\snaptogrid\vbox
- {\copy\currenttopcolumnbox
- \hbox{\vphantom{\vskip\floatheight}}}% known from previous
- \whitespace % nodig ?
- \blank[\rootfloatparameter\c!spaceafter]}%
- \else
- \page_floats_get_info\s!text
- \ifdim\floatwidth>\hsize
- \dimen0\dimexpr\floatwidth+\intercolumnwidth+.5pt\relax
- \dimen2\dimexpr\hsize +\intercolumnwidth+.5pt\relax
- \divide\dimen0 \dimen2
- \count0\dimen0
- \advance\count0 \plusone
- \ifnum\count0>\count2
- \count0\zerocount
+ \def\doflushcolumnfloats
+ {\ifpostponecolumnfloats\else
+ \bgroup
+ \forgetall
+ \ifconditional\c_page_floats_some_waiting
+ \dimen8\zeropoint
+ \dimen4\zeropoint
+ \count0\zerocount % count0 can be used local
+ \count2\nofcolumns % count2 can be used local
+ \dohandleallcolumns
+ {\ifnum\count0>\zerocount % the wide one's reserved space
+ \global\setbox\currenttopcolumnbox\vbox
+ {\snaptogrid\vbox
+ {\copy\currenttopcolumnbox
+ \hbox{\vphantom{\vskip\floatheight}}}% known from previous
+ \whitespace % nodig ?
+ \blank[\rootfloatparameter\c!spaceafter]}%
\else
- \dimen0\dimexpr\count0\hsize+\count0\intercolumnwidth-\intercolumnwidth\relax
- \page_floats_flush\s!text\plusone
- \ifdim\floatwidth>\finalcolumntextwidth % better somewhere else too
- \global\setbox\floatbox\hbox to \finalcolumntextwidth{\hss\box\floatbox\hss}%
- \fi % otherwise the graphic may disappear
- \global\setbox\floatbox\hbox to \dimen0
- {\processaction[\rootfloatparameter\c!location] % how easy to forget
- [ \v!left=>\box\floatbox\hss,
- \v!right=>\hss\box\floatbox,
- \s!default=>\hss\box\floatbox\hss,
- \s!unknown=>\hss\box\floatbox\hss]}%
+ \page_floats_get_info\s!text
+ \ifdim\floatwidth>\hsize
+ \dimen0\dimexpr\floatwidth+\d_page_mul_distance+.5pt\relax
+ \dimen2\dimexpr\hsize +\d_page_mul_distance+.5pt\relax
+ \divide\dimen0 \dimen2
+ \count0\dimen0
+ \advance\count0 \plusone
+ \ifnum\count0>\count2
+ \count0\zerocount
+ \else
+ \dimen0\dimexpr\count0\hsize+\count0\d_page_mul_distance-\d_page_mul_distance\relax
+ \page_floats_flush\s!text\plusone
+ \ifdim\floatwidth>\makeupwidth % better somewhere else too
+ \global\setbox\floatbox\hbox to \makeupwidth{\hss\box\floatbox\hss}%
+ \fi % otherwise the graphic may disappear
+ \global\setbox\floatbox\hbox to \dimen0
+ {\processaction[\rootfloatparameter\c!location] % how easy to forget
+ [ \v!left=>\box\floatbox\hss,
+ \v!right=>\hss\box\floatbox,
+ \s!default=>\hss\box\floatbox\hss,
+ \s!unknown=>\hss\box\floatbox\hss]}%
+ \fi
+ \showmessage\m!columns{13}\empty
+ \else
+ \page_floats_flush\s!text\plusone
+ \ifdim\floatwidth>\makeupwidth % better somewhere else too
+ \global\setbox\floatbox\hbox to \makeupwidth{\hss\box\floatbox\hss}%
+ \fi % otherwise the graphic may disappear
+ % \showmessage\m!columns{13}\empty
+ \fi
+ \ifdim\ht\floatbox>\zeropoint\relax
+ \global\setbox\currenttopcolumnbox\vbox
+ {\snaptogrid\vbox
+ {\box\currenttopcolumnbox % was copy
+ \box\floatbox}
+ \whitespace % nodig ?
+ \blank[\rootfloatparameter\c!spaceafter]}%
+ \fi
+ \dimen6\htdp\currenttopcolumnbox
\fi
- \showmessage\m!columns{13}\empty
- \else
- \page_floats_flush\s!text\plusone
- \ifdim\floatwidth>\finalcolumntextwidth % better somewhere else too
- \global\setbox\floatbox\hbox to \finalcolumntextwidth{\hss\box\floatbox\hss}%
- \fi % otherwise the graphic may disappear
- % \showmessage\m!columns{13}\empty
- \fi
- \ifdim\ht\floatbox>\zeropoint\relax
- \global\setbox\currenttopcolumnbox\vbox
- {\snaptogrid\vbox
- {\box\currenttopcolumnbox % was copy
- \box\floatbox}
- \whitespace % nodig ?
- \blank[\rootfloatparameter\c!spaceafter]}%
- \fi
- \dimen6\htdp\currenttopcolumnbox
- \fi
- \ifdim\dimen4<\ht\currenttopcolumnbox
- \dimen4\ht\currenttopcolumnbox
- \fi
- \advance\dimen8 \dimen6
- \advance\count2 \minusone
- \advance\count0 \minusone }%
- \page_otr_command_set_vsize
- \global\advance\vsize -\dimen8
- \global\pagegoal\vsize
- \else
- % \page_mul_command_flush_floats % does not snap!
- \fi
- \egroup
- \fi}
+ \ifdim\dimen4<\ht\currenttopcolumnbox
+ \dimen4\ht\currenttopcolumnbox
+ \fi
+ \advance\dimen8 \dimen6
+ \advance\count2 \minusone
+ \advance\count0 \minusone }%
+ \page_otr_command_set_vsize
+ \global\advance\vsize -\dimen8
+ \global\pagegoal\vsize
+ \else
+ % \page_mul_command_flush_floats % does not snap!
+ \fi
+ \egroup
+ \fi}
%D The next macro can be used to flush floats in the current stream. No
%D width checking is (yet) done.
-\def\insertcolumnfloats
- {\doloop
- {\ifconditional\c_page_floats_some_waiting
- \bgroup
- \forgetall
- % no check for width
- \page_floats_get
- \blank[\rootfloatparameter\c!spacebefore]
- \snaptogrid\vbox{\copy\floatbox}
- \blank[\rootfloatparameter\c!spaceafter]
- \egroup
- \else
- \exitloop
- \fi}}
+ \def\insertcolumnfloats
+ {\doloop
+ {\ifconditional\c_page_floats_some_waiting
+ \bgroup
+ \forgetall
+ % no check for width
+ \page_floats_get
+ \blank[\rootfloatparameter\c!spacebefore]
+ \snaptogrid\vbox{\copy\floatbox}
+ \blank[\rootfloatparameter\c!spaceafter]
+ \egroup
+ \else
+ \exitloop
+ \fi}}
%D This were the multi||column routines. They can and need to be improved
%D but at the moment their behaviour is acceptable.
@@ -1422,55 +1425,21 @@
% 3 \input tufte \par \placefigure{}{\framed[width=\hsize,height=3cm]{3}}
% \stopcolumns
-\unexpanded\def\setupcolumns
- {\dosingleempty\dosetupcolumns}
-
-\def\dosetupcolumns[#1]%
- {\getparameters[\??kl][#1]%
- \nofcolumns\@@kln\relax
- \processaction
- [\@@klrule]
- [ \v!on=>\let\betweencolumns\linebetweencolumns,
- \v!off=>\let\betweencolumns\spacebetweencolumns,
- \s!default=>\let\betweencolumns\spacebetweencolumns,
- \s!unknown=>\let\betweencolumns\@@klrule]}
-
-\def\linebetweencolumns
- {\bgroup
- \starttextproperties
- \ifdim\@@kldistance>\zeropoint
- \dimen0=\@@kldistance
- \else
- \dimen0=\linewidth % hm, weird
- \fi
- \advance\dimen0 -\linewidth
- \hskip.5\dimen0
- \vrule
- \!!width\linewidth
- \ifnum\bottomraggednessmode=\plustwo % baselinebottom
- \!!depth\strutdepth
- \fi
- \hskip.5\dimen0\relax
- \stoptextproperties
- \egroup}
-
-\def\spacebetweencolumns
- {\hskip\@@kldistance}
-
-\presetlocalframed[\??kl]
-
-\def\backgroundfinishcolumnbox
- {\doifinsetelse\@@kloffset{\v!none,\v!overlay}
- {\let\@@kloffset\!!zeropoint}
- {\scratchdimen\@@kloffset
- \advance\scratchdimen -\@@klrulethickness
- \edef\@@kloffset{\the\scratchdimen}}%
- \localframed
- [\??kl]
- [\c!strut=\v!no,
- \c!width=\v!fit,
- \c!height=\v!fit,
- \c!align=]}
+ % \def\backgroundfinishcolumnbox
+ % {\doifinsetelse\@@kloffset{\v!none,\v!overlay}
+ % {\let\@@kloffset\!!zeropoint}
+ % {\scratchdimen\@@kloffset
+ % \advance\scratchdimen -\@@klrulethickness
+ % \edef\@@kloffset{\the\scratchdimen}}%
+ % \localframed
+ % [\??kl]
+ % [\c!strut=\v!no,
+ % \c!width=\v!fit,
+ % \c!height=\v!fit,
+ % \c!align=]}
+
+ \def\backgroundfinishcolumnbox
+ {}
% to be reconsidered ... (in any case they need to be unexpandable sinze 2011.12.30)
@@ -1478,149 +1447,196 @@
\unexpanded\def\page_columns_align_option_no {\stretchcolumnsfalse\inheritcolumnsfalse}% todo: new key
\unexpanded\def\page_columns_align_option_text{\stretchcolumnsfalse\inheritcolumnstrue }%
+\newtoks\t_page_mul_initialize
+
\unexpanded\def\startcolumns
- {\dosingleempty\dostartcolumns}
+ {\dosingleempty\page_mul_start}
-\def\dostartcolumns[#1]% %% \startcolumns
+\def\page_mul_start[#1]% %% \startcolumns
{\bgroup
- \let\stopcolumns\egroup
\ifinsidecolumns
+ \page_mul_start_nop
\else
\iffirstargument
\setupcolumns[#1]%
\fi
- \ifnum\@@kln>1\relax
- \whitespace
- \begingroup
- \doif\@@kloption\v!background
- {\let\finishcolumnbox\backgroundfinishcolumnbox
- \let\columntextoffset\@@kloffset}%
- \ifx\@@klcommand\empty\else
- \let\postprocesscolumnline\@@klcommand
- \fi
- \doifelsenothing\@@klheight
- \heightencolumnsfalse
- \heightencolumnstrue
- \doifelse\@@kldirection\v!right
- \reversecolumnsfalse
- \reversecolumnstrue
- \doifelse\@@klbalance\v!yes
- \balancecolumnstrue
- \balancecolumnsfalse
- \installalign\v!yes {\page_columns_align_option_yes }%
- \installalign\v!no {\page_columns_align_option_no }%
- \installalign\v!text{\page_columns_align_option_text}%
- \stretchcolumnsfalse
- \inheritcolumnstrue
- \doifsomething\@@klalign{\expanded{\setupalign[\@@klalign]}}%
- \nofcolumns\@@kln
- \edef\fixedcolumnheight{\@@klheight}%
- \edef\minbalancetoplines{\@@klntop}%
- \setuptolerance[\@@kltolerance]% %% \startcolumns
- \setupblank[\@@klblank]%
- \ifdim\s_spac_whitespace_parskip>\zeropoint\relax
- \setupwhitespace[\@@klblank]%
- \fi
- \unexpanded\def\stopcolumns
- {\endmulticolumns
- \global\insidecolumnsfalse
- \endgroup
- \egroup}%
- \global\insidecolumnstrue
- \beginmulticolumns
+ \nofcolumns\columnsparameter\c!n\relax
+ \ifnum\nofcolumns>\plusone
+ \page_mul_start_yes
+ \else
+ \page_mul_start_nop
\fi
\fi}
-\installcolumnbreakmethod \s!multicolumn \v!preference
- {\goodbreak}
+\unexpanded\def\page_mul_start_nop
+ {\let\stopcolumns\page_mul_stop_nop}
-% \installcolumnbreakmethod \s!multicolumn \v!yes
-% {\par % todo: since
-% {\testrulewidth\zeropoint\ruledvskip\textheight} % we misuse a
-% \penalty-200 % side effect
-% \vskip-\textheight
-% }% bugged : \prevdepth-\thousandpoint} % signals top of column to \blank
+\unexpanded\def\page_mul_stop_nop
+ {\egroup}
-\installcolumnbreakmethod \s!multicolumn \v!yes
- {\par
+\unexpanded\def\page_mul_start_yes
+ {\whitespace
\begingroup
- \normaloffinterlineskip
- \normalpenalty\plustenthousand
- \vbox to \textheight{}%
- \endgroup
- \penalty-200
- \vskip-\textheight
- } % bugged : \prevdepth-\thousandpoint} % signals top of column to \blank
-
-%D New: only at start of columns; may change ! Rather interwoven and therefore
-%D to be integrated when the multi column modules are merged.
-
-\unexpanded\def\setupcolumnspan[#1]%
- {\getparameters[\??ks][#1]}
-
-\presetlocalframed
- [\??ks]
-
-\setupcolumnspan
- [\c!n=2,
- \c!offset=\v!overlay,
- \c!frame=\v!off]
+ \let\stopcolumns\page_mul_stop_indeed
+ \global\insidecolumnstrue
+ \the\t_page_mul_initialize
+ %
+ \flushnotes
+ \begingroup
+ %
+ \d_page_mul_leftskip\leftskip
+ \d_page_mul_rightskip\rightskip
+ \leftskip\zeropoint
+ \rightskip\zeropoint
+ %
+ \widowpenalty\zerocount % will become option
+ \clubpenalty \zerocount % will become option
+ %
+ \page_floats_column_push_saved
+ %
+ \ifdim\dimexpr\pagetotal+\parskip+\openlineheight\relax<\pagegoal
+ \allowbreak
+ \else
+ \break % sometimes fails
+ \fi
+ \appendtoks
+ \topskip1\topskip % best a switch
+ \to \everybodyfont
+ \the\everybodyfont % ugly here
+ \saveinterlinespace % ugly here
+ %
+ \initializecolumns\nofcolumns
+ %
+ \hangafter\zerocount
+ \hangindent\zeropoint
+ \reseteverypar
+ \ifdim\pagetotal=\zeropoint \else
+ \verticalstrut
+ \vskip-\struttotal
+ \fi
+ \global\savedpagetotal\pagetotal
+ \setupoutputroutine[\s!multicolumn]%
+ \c_page_mul_routine\c_page_mul_routine_intercept
+ \page_otr_trigger_output_routine % no \holdinginserts=1, can make footnote disappear !
+ \global\d_page_mul_preceding_height\ht\b_page_mul_preceding
+ \c_page_mul_routine\c_page_mul_routine_continue
+ \page_mul_initialize_floats
+ \dohandleallcolumns{\global\setbox\currenttopcolumnbox\emptybox}%
+ \checkbegincolumnfootnotes
+ \page_otr_command_set_hsize
+ \page_otr_command_set_vsize}
-\newbox\b_page_columns_span \let\postprocesscolumnspanbox\gobbleoneargument
+\setnewconstant\multicolumnendsyncmethod\plusone % 1: old sync 2: new sync (cont-loc/project) / may fail ! ! ! !
-\def\dostartcolumnspan[#1]%
- {\bgroup
- \setupcolumnspan[#1]%
- \forgetall
- \ifinsidecolumns
- \advance\hsize \intercolumnwidth
- \hsize\@@ksn\hsize
- \advance\hsize -\intercolumnwidth
+\unexpanded\def\page_mul_stop_indeed
+ {\relax
+ \ifnum\multicolumnendsyncmethod=\plustwo
+ \synchronizeoutput
+ \else
+ % don't collapse these
+ \vskip \lineheight
+ \vskip-\lineheight % take footnotes into account
\fi
- \dowithnextboxcs\dofinishcolumnsetspan\vbox\bgroup
- %\topskipcorrection % becomes an option !
- \EveryPar{\begstrut\EveryPar{}}} % also !
-
-\def\dofinishcolumnsetspan
- {\setbox\b_page_columns_span\flushnextbox
- \ifinsidecolumns\wd\b_page_columns_span\hsize\fi
- \postprocesscolumnspanbox\b_page_columns_span
- \scratchdimen\ht\b_page_columns_span
- \setbox\b_page_columns_span\hbox % depth to be checked, probably option!
- {\localframed[\??ks][\c!offset=\v!overlay]{\box\b_page_columns_span}}%
- \ht\b_page_columns_span\scratchdimen
- \dp\b_page_columns_span\strutdp
- \wd\b_page_columns_span\hsize
- \ifinsidecolumns
- \ifnum\@@ksn>1
- \page_otr_command_set_vsize
- \dohandleallcolumns
- {\ifnum\currentcolumn>\@@ksn\else
- \global\setbox\currenttopcolumnbox=\vbox
- {\ifnum\currentcolumn=1
- \snaptogrid\vbox{\copy\b_page_columns_span}
- \else
- \snaptogrid\vbox{\vphantom{\copy\b_page_columns_span}}
- \fi}%
- \wd\currenttopcolumnbox\hsize
- \global\advance\vsize -\ht\currenttopcolumnbox
- \fi}
- \global\pagegoal\vsize
- \else
- \snaptogrid\vbox{\box\b_page_columns_span}
+ \doflushcolumnfloat % added recently
+ %\doflushcolumnfloats % no, since it results in wrong top floats
+ \flushnotes % before start of columns
+ \par
+ \ifbalancecolumns
+ \ifnum\multicolumnendsyncmethod=\plusone
+ \c_page_mul_routine\c_page_mul_routine_continue
+ \goodbreak
\fi
+ \c_page_mul_routine\c_page_mul_routine_balance
\else
- \snaptogrid\vbox{\box\b_page_columns_span}
+ \goodbreak
\fi
- \endgraf
- \ifvmode\prevdepth\strutdp\fi
- \egroup}
+ % still the multi column routine
+ \page_otr_trigger_output_routine % the prevdepth is important, try e.g. toclist in
+ \prevdepth\zeropoint % columns before some noncolumned text text
+ %
+ \c_page_mul_routine\c_page_mul_routine_regular
+ %
+ \ifvoid\b_page_mul_preceding\else
+ \unvbox\b_page_mul_preceding
+ \fi
+ \global\d_page_mul_preceding_height\zeropoint
+ \endgroup % here
+ \nofcolumns\plusone
+ \page_otr_command_set_vsize
+ \checkendcolumnfootnotes
+ \dosomebreak\allowbreak
+ \page_floats_column_pop_saved
+ %
+ \global\insidecolumnsfalse
+ \endgroup
+ \egroup}%
+
+\appendtoks
+ \edef\p_option{\columnsparameter\c!option}%
+ \ifx\p_option\v!background
+ \let\finishcolumnbox\backgroundfinishcolumnbox
+ \fi
+ \d_page_mul_offset\columnsparameter\c!offset\relax
+ \edef\p_command{\columnsparameter\c!command}%
+ \ifx\p_command\empty \else
+ \let\postprocesscolumnline\p_command
+ \fi
+ \edef\p_height{\columnsparameter\c!height}%
+ \ifx\p_height\empty
+ \d_page_mul_forced_height\textheight
+ \heightencolumnsfalse
+ \else
+ \d_page_mul_forced_height\p_height\relax
+ \heightencolumnstrue
+ \fi
+ \edef\p_direction{\columnsparameter\c!direction}%
+ \ifx\p_direction\v!right
+ \setfalse\c_page_mul_reverse
+ \else
+ \settrue\c_page_mul_reverse
+ \fi
+ \edef\p_balance{\columnsparameter\c!balance}%
+ \ifx\p_balance\v!yes
+ \balancecolumnstrue
+ \else
+ \balancecolumnsfalse
+ \fi
+ \installalign\v!yes {\page_columns_align_option_yes }%
+ \installalign\v!no {\page_columns_align_option_no }%
+ \installalign\v!text{\page_columns_align_option_text}%
+ \stretchcolumnsfalse
+ \inheritcolumnstrue
+ \edef\p_align{\columnsparameter\c!align}%
+ \ifx\p_align\empty \else
+ \setupalign[\p_align]%
+ \fi
+ \edef\p_tolerance{\columnsparameter\c!tolerance}%
+ \ifx\p_tolerance\empty \else
+ \setuptolerance[\p_tolerance]%
+ \fi
+ \edef\p_blank{\columnsparameter\c!blank}%
+ \ifx\p_blank\empty \else
+ \setupblank[\p_blank]%
+ \fi
+ \ifdim\s_spac_whitespace_parskip>\zeropoint\relax
+ \setupwhitespace[\p_blank]%
+ \fi
+ \c_page_mul_balance_minimum\columnsparameter\c!ntop\relax
+ \edef\p_page_mul_rule{\columnsparameter\c!rule}%
+ \expandcheckedcsname\??columnseparators\p_page_mul_rule\s!unknown
+\to \t_page_mul_initialize
+
+%D Columns breaks
-\unexpanded\def\startcolumnspan
- {\dosingleempty\dostartcolumnspan}
+\installcolumnbreakmethod \s!multicolumn \v!preference
+ {\goodbreak}
-\unexpanded\def\stopcolumnspan
- {\egroup}
+\installcolumnbreakmethod \s!multicolumn \v!yes
+ {\vskip\textheight
+ \penalty-200 % we can mark and intercept this
+ \vskip-\textheight}
+
+%D Next we initialize the lot:
\setupcolumns
[\c!n=2,
@@ -1638,19 +1654,85 @@
\c!rulethickness=\linewidth,
\c!offset=.5\bodyfontsize]
-%D Undocumented and still under development.
+%D New: only at start of columns; may change ! Rather interwoven and therefore
+%D to be integrated when the multi column modules are merged.
+
+ \unexpanded\def\setupcolumnspan[#1]%
+ {\getparameters[\??ks][#1]}
+
+ \presetlocalframed
+ [\??ks]
+
+ \setupcolumnspan
+ [\c!n=2,
+ \c!offset=\v!overlay,
+ \c!frame=\v!off]
+
+ \newbox\b_page_columns_span \let\page_mul_postprocess_spanbox\gobbleoneargument
+
+ \unexpanded\def\startcolumnspan
+ {\dosingleempty\dostartcolumnspan}
+
+ \unexpanded\def\stopcolumnspan
+ {\egroup}
+
+ \def\dostartcolumnspan[#1]%
+ {\bgroup
+ \setupcolumnspan[#1]%
+ \forgetall
+ \ifinsidecolumns
+ \advance\hsize \d_page_mul_distance
+ \hsize\@@ksn\hsize
+ \advance\hsize -\d_page_mul_distance
+ \fi
+ \dowithnextboxcs\dofinishcolumnsetspan\vbox\bgroup
+ %\topskipcorrection % becomes an option !
+ \EveryPar{\begstrut\EveryPar{}}} % also !
+
+ \def\dofinishcolumnsetspan
+ {\setbox\b_page_columns_span\flushnextbox
+ \ifinsidecolumns\wd\b_page_columns_span\hsize\fi
+ \page_mul_postprocess_spanbox\b_page_columns_span
+ \scratchdimen\ht\b_page_columns_span
+ \setbox\b_page_columns_span\hbox % depth to be checked, probably option!
+ {\localframed[\??ks][\c!offset=\v!overlay]{\box\b_page_columns_span}}%
+ \ht\b_page_columns_span\scratchdimen
+ \dp\b_page_columns_span\strutdp
+ \wd\b_page_columns_span\hsize
+ \ifinsidecolumns
+ \ifnum\@@ksn>1
+ \page_otr_command_set_vsize
+ \dohandleallcolumns
+ {\ifnum\currentcolumn>\@@ksn\else
+ \global\setbox\currenttopcolumnbox=\vbox
+ {\ifnum\currentcolumn=1
+ \snaptogrid\vbox{\copy\b_page_columns_span}
+ \else
+ \snaptogrid\vbox{\vphantom{\copy\b_page_columns_span}}
+ \fi}%
+ \wd\currenttopcolumnbox\hsize
+ \global\advance\vsize -\ht\currenttopcolumnbox
+ \fi}
+ \global\pagegoal\vsize
+ \else
+ \snaptogrid\vbox{\box\b_page_columns_span}
+ \fi
+ \else
+ \snaptogrid\vbox{\box\b_page_columns_span}
+ \fi
+ \endgraf
+ \ifvmode\prevdepth\strutdp\fi
+ \egroup}
+
+%D Undocumented and still under development.\ifdefined\startsimplecolumns \else
\unexpanded\def\startsimplecolumns
- {\dosingleempty\dostartsimplecolumns}
+ {\dosingleempty\page_mul_simple_start}
-\def\dostartsimplecolumns[#1]%
+\def\page_mul_simple_start[#1]%
{\bgroup
+ \setsimplecolumnshsize[#1]%
\nopenalties
- \getparameters[\??kl]
- [\c!width=\hsize,\c!distance=1.5\bodyfontsize,%
- \c!n=2,\c!lines=0,#1]%
- \let\rigidcolumnlines\@@kllines
- \setrigidcolumnhsize\@@klwidth\@@kldistance\@@kln
\setbox\scratchbox\vbox\bgroup
\forgetall} % \blank[\v!disable]
@@ -1661,35 +1743,44 @@
\egroup}
\unexpanded\def\setsimplecolumnshsize[#1]%
- {\getparameters[\??kl][\c!width=\hsize,\c!distance=1.5\bodyfontsize,\c!n=2,\c!lines=0,#1]%
- \let\rigidcolumnlines\@@kllines
- \setrigidcolumnhsize\@@klwidth\@@kldistance\@@kln}
+ {\getdummyparameters
+ [\c!width=\hsize,
+ \c!distance=1.5\bodyfontsize,
+ \c!n=2,
+ \c!lines=0,
+ #1]%
+ \edef\rigidcolumnlines
+ {\directdummyparameter\c!lines}%
+ \setrigidcolumnhsize
+ {\directdummyparameter\c!width}%
+ {\directdummyparameter\c!distance}%
+ {\directdummyparameter\c!n}}
\let\page_mul_command_package_contents\page_one_command_package_contents
\let\page_mul_command_flush_float_box \page_one_command_flush_float_box
\defineoutputroutine
[\s!multicolumn]
- [\s!page_otr_command_routine =\page_mul_command_routine,
- \s!page_otr_command_package_contents =\page_mul_command_package_contents,
- \s!page_otr_command_set_vsize =\page_mul_command_set_vsize,
- \s!page_otr_command_set_hsize =\page_mul_command_set_hsize,
- \s!page_otr_command_next_page =\page_mul_command_next_page,
- \s!page_otr_command_next_page_and_inserts =\page_mul_command_next_page_and_inserts,
- % \s!page_otr_command_synchronize_hsize =\page_mul_command_synchronize_hsize,
- % \s!page_otr_command_set_top_insertions =\page_mul_command_set_top_insertions,
- % \s!page_otr_command_set_bottom_insertions =\page_mul_command_set_bottom_insertions,
- \s!page_otr_command_flush_top_insertions =\page_mul_command_flush_top_insertions,
- % \s!page_otr_command_flush_bottom_insertions =\page_mul_command_flush_bottom_insertions,
- % \s!page_otr_command_set_float_hsize =\page_mul_command_set_float_hsize,
- \s!page_otr_command_check_if_float_fits =\page_mul_command_check_if_float_fits,
- \s!page_otr_command_flush_float_box =\page_mul_command_flush_float_box,
- \s!page_otr_command_synchronize_side_floats =\page_mul_command_synchronize_side_floats,
- \s!page_otr_command_side_float_output =\page_mul_command_side_float_output,
- \s!page_otr_command_flush_floats =\page_mul_command_flush_floats,
- \s!page_otr_command_flush_side_floats =\page_mul_command_flush_side_floats,
- \s!page_otr_command_flush_saved_floats =\page_mul_command_flush_saved_floats
- % \s!page_otr_command_flush_margin_blocks =\page_mul_command_flush_margin_blocks, % not used
+ [\s!page_otr_command_routine =\page_mul_command_routine,
+ \s!page_otr_command_package_contents =\page_mul_command_package_contents,
+ \s!page_otr_command_set_vsize =\page_mul_command_set_vsize,
+ \s!page_otr_command_set_hsize =\page_mul_command_set_hsize,
+ \s!page_otr_command_next_page =\page_mul_command_next_page,
+ \s!page_otr_command_next_page_and_inserts =\page_mul_command_next_page_and_inserts,
+ % \s!page_otr_command_synchronize_hsize =\page_mul_command_synchronize_hsize,
+ % \s!page_otr_command_set_top_insertions =\page_mul_command_set_top_insertions,
+ % \s!page_otr_command_set_bottom_insertions =\page_mul_command_set_bottom_insertions,
+ \s!page_otr_command_flush_top_insertions =\page_mul_command_flush_top_insertions,
+ % \s!page_otr_command_flush_bottom_insertions=\page_mul_command_flush_bottom_insertions,
+ % \s!page_otr_command_set_float_hsize =\page_mul_command_set_float_hsize,
+ \s!page_otr_command_check_if_float_fits =\page_mul_command_check_if_float_fits,
+ \s!page_otr_command_flush_float_box =\page_mul_command_flush_float_box,
+ \s!page_otr_command_synchronize_side_floats=\page_mul_command_synchronize_side_floats,
+ \s!page_otr_command_side_float_output =\page_mul_command_side_float_output,
+ \s!page_otr_command_flush_floats =\page_mul_command_flush_floats,
+ \s!page_otr_command_flush_side_floats =\page_mul_command_flush_side_floats,
+ \s!page_otr_command_flush_saved_floats =\page_mul_command_flush_saved_floats
+ % \s!page_otr_command_flush_margin_blocks =\page_mul_command_flush_margin_blocks, % not used
]
\protect \endinput
diff --git a/tex/context/base/page-not.mkiv b/tex/context/base/page-not.mkiv
index 7fae16419..d7602bd26 100644
--- a/tex/context/base/page-not.mkiv
+++ b/tex/context/base/page-not.mkiv
@@ -41,11 +41,13 @@
\newdimen\totalinsertionheight
-\def\settotalinsertionheight
+\unexpanded\def\settotalinsertionheight
{\calculatetotalnoteheight
- \totalinsertionheight\totalnoteheight
- \addinsertionheight\c_page_floats_insertions_top \to\totalinsertionheight
- \addinsertionheight\c_page_floats_insertions_bottom\to\totalinsertionheight}
+ \totalinsertionheight\dimexpr
+ \totalnoteheight
+ +\page_insert_insertion_height\s!topfloat
+ +\page_insert_insertion_height\s!bottomfloat
+ \relax}
% hm
diff --git a/tex/context/base/page-one.mkiv b/tex/context/base/page-one.mkiv
index e9ca80e2b..9c740dbc2 100644
--- a/tex/context/base/page-one.mkiv
+++ b/tex/context/base/page-one.mkiv
@@ -197,18 +197,19 @@
\global\advance\d_page_floats_inserted_top\dimexpr\ht\floatbox+\dp\floatbox+\s_page_one_between_top_insert\relax}
\def\page_one_insert_top_float % maybe remember last beforeskip
- {\insert\c_page_floats_insertions_top
- {\forgetall
- \ifconditional\c_page_one_top_of_insert
- \ifconditional\c_page_one_correct_top_insert
- \topskipcorrection % [xx] new: see icare topbleed
- \kern-\lineskip
- \par
- \prevdepth\maxdimen
- \fi
- \fi
- \page_otr_command_flush_float_box
- \vskip\s_page_one_between_top_insert}}
+ {\insert\namedinsertionnumber\s!topfloat\bgroup
+ \forgetall
+ \ifconditional\c_page_one_top_of_insert
+ \ifconditional\c_page_one_correct_top_insert
+ \topskipcorrection % [xx] new: see icare topbleed
+ \kern-\lineskip
+ \par
+ \prevdepth\maxdimen
+ \fi
+ \fi
+ \page_otr_command_flush_float_box
+ \vskip\s_page_one_between_top_insert
+ \egroup}
\unexpanded\def\page_one_command_set_top_insertions
{\bgroup
@@ -267,10 +268,11 @@
\page_floats_get
\global\advance\d_page_floats_inserted_bottom\dimexpr\ht\floatbox+\dp\floatbox+\d_strc_floats_top\relax
\ifdim\d_page_floats_inserted_bottom<\pagegoal\relax
- \insert\c_page_floats_insertions_bottom
- {\forgetall
- \blank[\rootfloatparameter\c!spacebefore]%
- \page_otr_command_flush_float_box}%
+ \insert\namedinsertionnumber\s!bottomfloat\bgroup
+ \forgetall
+ \blank[\rootfloatparameter\c!spacebefore]%
+ \page_otr_command_flush_float_box
+ \egroup
\ifconditional\c_page_floats_some_waiting
\advance\noffloatinserts \plusone
\else
@@ -291,9 +293,9 @@
\page_one_command_set_bottom_insertions_indeed}
\unexpanded\def\page_one_command_flush_top_insertions
- {\ifvoid\c_page_floats_insertions_top\else
+ {\ifvoid\namedinsertionnumber\s!topfloat\else
\ifgridsnapping
- \box\c_page_floats_insertions_top
+ \box\namedinsertionnumber\s!topfloat
\vskip-\topskip
\vskip\strutheight % [xx] new: see icare topbleed
\else
@@ -304,20 +306,20 @@
\vskip-\topskip
\vskip\strutheight
\fi
- \unvbox\c_page_floats_insertions_top
+ \unvbox\namedinsertionnumber\s!topfloat
\fi
\fi
\global\d_page_floats_inserted_top\zeropoint}
\unexpanded\def\page_one_command_flush_bottom_insertions
- {\ifvoid\c_page_floats_insertions_bottom\else
+ {\ifvoid\namedinsertionnumber\s!bottomfloat\else
\ifgridsnapping
% \floatparameter\c!bottombefore
- \snaptogrid\hbox{\box\c_page_floats_insertions_bottom}%
+ \snaptogrid\hbox{\box\namedinsertionnumber\s!bottomfloat}%
% \floatparameter\c!bottomafter
\else
\floatparameter\c!bottombefore
- \unvbox\c_page_floats_insertions_bottom
+ \unvbox\namedinsertionnumber\s!bottomfloat
\floatparameter\c!bottomafter
\fi
\fi
@@ -549,11 +551,11 @@
\def\page_one_place_float_bottom_indeed
{\global\advance\d_page_floats_inserted_bottom\dimexpr\ht\floatbox+\dp\floatbox+\d_strc_floats_top\relax
- \insert\c_page_floats_insertions_bottom
- {\forgetall
- \blank[\rootfloatparameter\c!spacebefore]%
- \page_otr_command_flush_float_box}%
- %\global\settrue\c_page_floats_not_permitted
+ \insert\namedinsertionnumber\s!bottomfloat\bgroup
+ \forgetall
+ \blank[\rootfloatparameter\c!spacebefore]%
+ \page_otr_command_flush_float_box
+ \egroup
\page_floats_report_total}
\def\page_one_place_float_face % links, rechts, midden, hoog, midden, laag
diff --git a/tex/context/base/page-otr.mkvi b/tex/context/base/page-otr.mkvi
index 19c308c32..e5433c866 100644
--- a/tex/context/base/page-otr.mkvi
+++ b/tex/context/base/page-otr.mkvi
@@ -258,8 +258,8 @@
\definesystemconstant{page_otr_command_flush_margin_blocks}
\definesystemconstant{singlecolumn}
-\definesystemconstant{multicolumn}
-\definesystemconstant{columnset}
+\definesystemconstant{multicolumn} % will move
+\definesystemconstant{columnset} % will move
\defineoutputroutinecommand
[\s!page_otr_command_routine,
diff --git a/tex/context/base/page-pst.mkiv b/tex/context/base/page-pst.mkiv
index 1078dda03..63fa54aa1 100644
--- a/tex/context/base/page-pst.mkiv
+++ b/tex/context/base/page-pst.mkiv
@@ -51,8 +51,8 @@
%newif \ifinpostponing % prevents nesting
-\newcount \c_page_postponed_blocks_next_page % set at the lua end
-\newconstant\c_page_postponed_busy
+\newcount \c_page_postponed_blocks_next_page % set at the lua end
+\newconditional\c_page_postponed_busy
\unexpanded\setvalue{\e!start\v!postponing}%
{\bgroup
diff --git a/tex/context/base/page-set.mkiv b/tex/context/base/page-set.mkiv
index c74c397e8..f0981443c 100644
--- a/tex/context/base/page-set.mkiv
+++ b/tex/context/base/page-set.mkiv
@@ -49,6 +49,17 @@
\newif\ifcolumnspread
\newif\iftracecolumnset % \tracecolumnsettrue
+\newif\ifforcecolumnsetgrid \forcecolumnsetgridtrue
+\newif\ifcollectingsetcontent % never set
+\newif\ifcarryoverfootnotes %\carryoverfootnotestrue
+\newif\iflastcolumnfootnotes % never set \lastcolumnfootnotestrue
+\newif\ifintermediatefootnotes
+
+\newbox\b_page_set_preceding
+\newbox\b_page_set_trailing
+
+\newdimen\d_page_set_local_hsize
+
\def\columnmaxcells {75} % runtime
\def\columnmaxfreecells {0} % runtime
\def\columngaplimit {0} % {5}
@@ -385,12 +396,12 @@
\hbox to \OTRSETmakeupwidth
{\dostepwiserecurse{#1}{#2}{#3}
{\mofcolumns\recurselevel
- \localcolumnwidth\OTRSETlocalwidth\mofcolumns
+ \d_page_set_local_hsize\OTRSETlocalwidth\mofcolumns
\setbox\scratchbox\hbox\localframed
[\??mc\OTRSETidentifier\number\mofcolumns]%
- [\c!width=\localcolumnwidth,\c!height=\!!heighta,\c!lines=]%
+ [\c!width=\d_page_set_local_hsize,\c!height=\!!heighta,\c!lines=]%
{}%
- \wd\scratchbox\localcolumnwidth
+ \wd\scratchbox\d_page_set_local_hsize
\ht\scratchbox\!!heighta
\ifcase\columndirection
\hskip\OTRSETgetparameter\c!distance\recurselevel
@@ -404,7 +415,7 @@
\hbox to \OTRSETmakeupwidth
{\dostepwiserecurse{#1}{#2}{#3}
{\mofcolumns\recurselevel
- \localcolumnwidth\OTRSETlocalwidth\mofcolumns
+ \d_page_set_local_hsize\OTRSETlocalwidth\mofcolumns
\offinterlineskip
\setbox\scratchbox\vbox to \!!heighta
{%\topskipcorrection % not needed
@@ -426,8 +437,8 @@
\ifcase\columndirection
\box\scratchbox
\else
- \hbox to \localcolumnwidth
- {\hskip\localcolumnwidth\llap{\box\scratchbox}}%
+ \hbox to \d_page_set_local_hsize
+ {\hskip\d_page_set_local_hsize\llap{\box\scratchbox}}%
\fi
\par}%
\ifcase\OTRSETbalancemethod
@@ -442,7 +453,7 @@
\kern\zeropoint
\vss
\fi}%
- \wd\scratchbox\localcolumnwidth % \textwidth
+ \wd\scratchbox\d_page_set_local_hsize % \textwidth
\page_marks_synchronize_column{#1}{#2}\recurselevel\scratchbox
\ifcase\columndirection
\hskip\OTRSETgetparameter\c!distance\recurselevel\box\scratchbox
@@ -496,7 +507,7 @@
\fi}
\def\OTRSETdoflush
- {\ifcollectingcontent
+ {\ifcollectingsetcontent
\global\mofcolumns\plusone
\else
\OTRSETdofinalflush
@@ -572,7 +583,7 @@
\fi}
\unexpanded\def\page_set_command_set_vsize % snap per sectie (gap here?)
- {\ifcollectingcontent \else % can be assigndimen
+ {\ifcollectingsetcontent \else % can be assigndimen
\OTRSETsetcolumnmaxcells % layout can be changed
\OTRSETskipstart % not that well tested
\OTRSETcheckinsert % added
@@ -589,9 +600,9 @@
\fi}
\def\page_set_command_set_hsize % of course this does not migrate outside the otr
- {\localcolumnwidth\OTRSETlocalwidth\mofcolumns
- \textwidth\localcolumnwidth
- \hsize\localcolumnwidth}
+ {\d_page_set_local_hsize\OTRSETlocalwidth\mofcolumns
+ \textwidth\d_page_set_local_hsize
+ \hsize\d_page_set_local_hsize}
\unexpanded\def\page_set_command_synchronize_hsize
{\ifcase0\getvalue{\??mc\??mc\c!width}\else % some width set
@@ -1806,46 +1817,46 @@
\ifx\lastskipinotr\undefined \newskip\lastskipinotr \fi
\installoutputroutine\OTRSETflushpreposttext
- {\global\setbox\precolumnbox\vbox
+ {\global\setbox\b_page_set_preceding\vbox
{\unvbox\normalpagebox
\global\lastskipinotr\lastskip}%
\ifdim\lastskipinotr>\zeropoint
- \global\setbox\precolumnbox\hbox
- {\lower\strutdepth\box\precolumnbox}%
+ \global\setbox\b_page_set_preceding\hbox
+ {\lower\strutdepth\box\b_page_set_preceding}%
\fi
- \dp\precolumnbox\strutdepth
+ \dp\b_page_set_preceding\strutdepth
\ifcarryoverfootnotes \else
- \global\setbox\postcolumnbox\vbox{\placebottomnotes}%
+ \global\setbox\b_page_set_trailing\vbox{\placebottomnotes}%
\fi}
\let\precolumnlines \!!zerocount
\let\postcolumnlines\!!zerocount
\def\OTRSEThandlepreposttext
- {\ifdim\ht\precolumnbox>\zeropoint % new
- \getnoflines{\ht\precolumnbox}%
+ {\ifdim\ht\b_page_set_preceding>\zeropoint % new
+ \getnoflines{\ht\b_page_set_preceding}%
\edef\precolumnlines{\the\noflines}%
\doOTRSETsetgridcells
{\copy\placeholderboxe}
\plusone\plusone\nofcolumns\noflines
% normal version (single column set)
- % {\box\precolumnbox}%
+ % {\box\b_page_set_preceding}%
% compensated for bodyfont change
{\hbox
{\OTRSETsetcorrectcellht
- \raise\scratchdimen\box\precolumnbox}}%
+ \raise\scratchdimen\box\b_page_set_preceding}}%
\else
\let\precolumnlines\!!zerocount
\fi
- \ifdim\ht\postcolumnbox>\zeropoint % new, otherwise empty bottom line
- \getnoflines{\ht\postcolumnbox}%
+ \ifdim\ht\b_page_set_trailing>\zeropoint % new, otherwise empty bottom line
+ \getnoflines{\ht\b_page_set_trailing}%
\edef\postcolumnlines{\the\noflines}%
\advance\columnfreecells -\noflines
\advance\columnfreecells \plusone
\doOTRSETsetgridcells
{\copy\placeholderboxe}
\plusone\columnfreecells\nofcolumns\noflines
- {\box\postcolumnbox}%
+ {\box\b_page_set_trailing}%
\else
\let\postcolumnlines\!!zerocount
\fi}
@@ -1858,7 +1869,7 @@
\def\OTRSETcheckgrid
{\topskip1\topskip
- \ifforcecolumngrid
+ \ifforcecolumnsetgrid
\widowpenalty\zerocount
\clubpenalty\zerocount
\brokenpenalty\zerocount
@@ -2049,7 +2060,10 @@
\let\OTRSETdodosettopinserts\relax % to be tested
\else
\xdef\totaltopinserted{\the\d_page_floats_inserted_top}%
- \insert\c_page_floats_insertions_top{\forgetall\box\scratchbox}% interlineskip ?
+ \insert\namedinsertionnumber\s!topfloat\bgroup
+ \forgetall
+ \box\scratchbox
+ \egroup
\ifconditional\c_page_floats_some_waiting
\advance\noffloatinserts \plusone
\else
@@ -2078,10 +2092,11 @@
\page_floats_get
\global\advance\d_page_floats_inserted_bottom\dimexpr\ht\floatbox+\dp\floatbox+\d_strc_floats_top\relax
\ifdim\d_page_floats_inserted_bottom<\pagegoal\relax
- \insert\c_page_floats_insertions_bottom
- {\forgetall
- \blank[\rootfloatparameter\c!spacebefore]%
- \page_otr_command_flush_float_box}%
+ \insert\namedinsertionnumber\s!bottomfloat\bgroup
+ \forgetall
+ \blank[\rootfloatparameter\c!spacebefore]%
+ \page_otr_command_flush_float_box
+ \egroup
\ifconditional\c_page_floats_some_waiting
\advance\noffloatinserts \plusone
\else
@@ -2102,27 +2117,27 @@
\OTRSETdodosetbotinserts}
\unexpanded\def\page_set_command_flush_top_insertions
- {\ifvoid\c_page_floats_insertions_top\else
+ {\ifvoid\namedinsertionnumber\s!topfloat\else
\ifvoid\columntopbox\mofcolumns
- \columnsettopbox\mofcolumns\box\c_page_floats_insertions_top
+ \columnsettopbox\mofcolumns\box\namedinsertionnumber\s!topfloat
\else
\columnsettopbox\mofcolumns\vbox % temp, must be better
{\forgetall
\offinterlineskip
\box\columntopbox\mofcolumns
- \box\c_page_floats_insertions_top}
+ \box\namedinsertionnumber\s!topfloat}
\fi
\fi
\global\d_page_floats_inserted_top\zeropoint\relax} % goes away
\unexpanded\def\page_set_command_flush_bottom_insertions
- {\ifvoid\c_page_floats_insertions_bottom \else
- \columnsetbotbox\mofcolumns\box\c_page_floats_insertions_bottom
+ {\ifvoid\namedinsertionnumber\s!bottomfloat \else
+ \columnsetbotbox\mofcolumns\box\namedinsertionnumber\s!bottomfloat
% \else
% \columnsetbotbox\mofcolumns\vbox % temp, must be better
% {\forgetall
% \offinterlineskip
-% \box\c_page_floats_insertions_bottom
+% \box\namedinsertionnumber\s!bottomfloat
% \box\columnbotbox\mofcolumns}
\fi
\global\d_page_floats_inserted_bottom\zeropoint\relax} % goes away
diff --git a/tex/context/base/page-sid.mkiv b/tex/context/base/page-sid.mkiv
index 629596c33..8989b04b5 100644
--- a/tex/context/base/page-sid.mkiv
+++ b/tex/context/base/page-sid.mkiv
@@ -210,10 +210,7 @@
\doloop
{\strut
\iftracesidefloats
- \color[darkgray]%
- {\baselinerulefalse
- \boxrulewidth.5\points
- \ruledhbox{\strut\kern\d_page_sides_width}}%
+ \color[darkgray]{\ruledhbox{\strut\kern\d_page_sides_width}}%
\fi
\par
\ifdim\dimexpr\d_page_sides_vsize-\pagetotal\relax>\zeropoint
diff --git a/tex/context/base/s-art-01.mkiv b/tex/context/base/s-art-01.mkiv
index 10b4de9ab..c8d849d8c 100644
--- a/tex/context/base/s-art-01.mkiv
+++ b/tex/context/base/s-art-01.mkiv
@@ -2,6 +2,8 @@
% \showframe
+\unprotect
+
\setuplayout
[\c!topspace=2cm,
\c!bottomspace=2.5cm,
@@ -33,4 +35,6 @@
[\c!style=\bf,
\c!after=]
+\protect
+
\stopmodule
diff --git a/tex/context/base/spac-ver.mkiv b/tex/context/base/spac-ver.mkiv
index 4ffdeaf85..5737fc201 100644
--- a/tex/context/base/spac-ver.mkiv
+++ b/tex/context/base/spac-ver.mkiv
@@ -1495,7 +1495,7 @@
\ruledvbox
\fi}
-\def\gridboxwidth{\ifcase\gridboxlinemode0\or.5\or.5\or0\else.5\fi\testrulewidth}
+\def\gridboxwidth{\ifcase\gridboxlinemode0\or.5\or.5\or0\else.5\fi\linewidth}
\unexpanded\def\setgridbox#1#2#3% maybe ifgridsnapping at outer level
{\setbox#1\gridboxvbox to #3 % given size
@@ -1503,10 +1503,10 @@
\resetteststrut
\offinterlineskip
\hsize#2%
- \baselinerulefalse
\ifnum\gridboxlinenomode=\plusthree
\gridboxlinenomode\ifodd\realpageno\plusone\else\plustwo\fi
\fi
+ \topskipcorrection
\gridboxvbox % calculated size
{\getrawnoflines{#3}% \getnoflines{#3}%
\scratchdimen\dimexpr#2+\lineheight\relax
@@ -1515,11 +1515,11 @@
\hskip-.5\lineheight\relax
\ifcase\gridboxlinenomode\or
\rlap
- {\hskip.2\bodyfontsize\hskip\scratchdimen
- \infofont\hbox to 1em{\hss\recurselevel}}%
+ {\hskip\dimexpr.2\bodyfontsize+\scratchdimen\relax
+ \infofont\hbox to \emwidth{\hss\recurselevel}}%
\or
\llap
- {\infofont\hbox to 1em{\hss\recurselevel}%
+ {\infofont\hbox to \emwidth{\hss\recurselevel}%
\hskip.2\bodyfontsize}%
\fi
\vrule
diff --git a/tex/context/base/status-files.pdf b/tex/context/base/status-files.pdf
index 259b6f7cc..5fb854019 100644
--- a/tex/context/base/status-files.pdf
+++ b/tex/context/base/status-files.pdf
Binary files differ
diff --git a/tex/context/base/status-lua.pdf b/tex/context/base/status-lua.pdf
index 691db3b2d..9c7987cca 100644
--- a/tex/context/base/status-lua.pdf
+++ b/tex/context/base/status-lua.pdf
Binary files differ
diff --git a/tex/context/base/status-mkiv.lua b/tex/context/base/status-mkiv.lua
index 7bd388abd..c2779d0b4 100644
--- a/tex/context/base/status-mkiv.lua
+++ b/tex/context/base/status-mkiv.lua
@@ -272,6 +272,11 @@ return {
status = "okay",
},
{
+ filename = "trac-ctx",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
filename = "supp-box",
marktype = "mkiv",
status = "okay",
@@ -312,12 +317,6 @@ return {
comment = "will grow",
},
{
- filename = "page-ins",
- marktype = "mkiv",
- status = "okay",
- comment = "dealing with insertions might change",
- },
- {
filename = "file-syn",
marktype = "mkvi",
status = "okay",
@@ -704,6 +703,12 @@ return {
comment = "code might end up elsewhere",
},
{
+ filename = "page-ins",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "dealing with insertions might change",
+ },
+ {
filename = "page-fac",
marktype = "mkiv",
status = "okay",
@@ -798,6 +803,12 @@ return {
comment = "will be reimplemented",
},
{
+ filename = "page-mix",
+ marktype = "mkiv",
+ status = "todo",
+ comment = "work in progress",
+ },
+ {
filename = "page-set",
marktype = "mkiv",
status = "todo",
diff --git a/tex/context/base/strc-itm.mkvi b/tex/context/base/strc-itm.mkvi
index a28eaacd8..5ecf72cc9 100644
--- a/tex/context/base/strc-itm.mkvi
+++ b/tex/context/base/strc-itm.mkvi
@@ -842,9 +842,6 @@
\let\startcollectitems\relax
\let\stopcollectitems \relax
-\ifdefined\startcolumns \else \unexpanded\def\startcolumns[#settings]{} \fi
-\ifdefined\stopcolumns \else \unexpanded\def\stopcolumns {} \fi
-
\letvalue{\??itemgroupalign\v!flushleft }\relax
\letvalue{\??itemgroupalign\v!right }\relax
\letvalue{\??itemgroupalign\v!flushright}\hfill
@@ -883,16 +880,31 @@
\def\strc_itemgroups_setup_symbol_asked
{\edef\strc_itemgroups_asked_symbol{\itemgroupparameter\c!symbol}}
-\def\strc_itemgroups_start_columns
- {\startcolumns
- [\c!n=\itemgroupparameter\c!n,
- \c!height=,
- \c!rule=\v!off,
- \c!balance=\v!yes,
- \c!align=\v!no]}
+\ifdefined\strc_itemgroups_start_columns
+
+ % already defined in page-mix
+
+\else
+
+ % will be redefined in page-mix
-\def\strc_itemgroups_stop_columns
- {\stopcolumns}
+ \ifdefined\startcolumns \else
+ \unexpanded\def\startcolumns[#settings]{}
+ \unexpanded\def\stopcolumns {}
+ \fi
+
+ \def\strc_itemgroups_start_columns
+ {\startcolumns
+ [\c!n=\itemgroupparameter\c!n,
+ \c!height=,
+ \c!rule=\v!off,
+ \c!balance=\v!yes,
+ \c!align=\v!no]}
+
+ \def\strc_itemgroups_stop_columns
+ {\stopcolumns}
+
+\fi
\unexpanded\def\stopitemgroup
{\stopcollectitems
diff --git a/tex/context/base/strc-not.mkvi b/tex/context/base/strc-not.mkvi
index 74e4345aa..05bca36ba 100644
--- a/tex/context/base/strc-not.mkvi
+++ b/tex/context/base/strc-not.mkvi
@@ -364,14 +364,12 @@
\installcorenamespace{noteinsertion}
-\def\currentnoteins{\csname\??noteinsertion\currentnote\endcsname}
-
\appendtoks
- \ifcsname\??noteinsertion\currentnote\endcsname\else
- \expandafter\installinsertion\csname\??noteinsertion\currentnote\endcsname\relax
- \normalexpanded{\t_strc_notes{\the\t_strc_notes\noexpand\strc_notes_process_list{\currentnote}}}%
- \fi
- \ctxlua{structures.notes.define("\currentnote","insert",\number\currentnoteins)}%
+ \defineinsertion[\currentnote]%
+ \doifinsertionelse\currentnote
+ {\normalexpanded{\t_strc_notes{\the\t_strc_notes\noexpand\strc_notes_process_list{\currentnote}}}}
+ \donothing
+ \ctxlua{structures.notes.define("\currentnote","insert",\number\namedinsertionnumber\currentnote)}%
\ifx\currentnoteparent\empty
\definenotation[\currentnote][\c!type=\v!note]%
\else
@@ -843,7 +841,7 @@
\ifx\p_factor\empty \else
\ifnum\p_factor<\zerocount \else
% \global
- \count\currentnoteins\p_factor % new: global
+ \count\namedinsertionnumber\currentnote\p_factor % new: global
\fi
\fi}
@@ -959,9 +957,9 @@
{\setfalse\c_strc_notes_delayed
\strc_notes_set_distance
\strc_notes_set_columns
- \global\count\currentnoteins\numexpr\plusthousand/\c_strc_notes_columns\relax
- \global\dimen\currentnoteins\ifnotelimit\dimexpr\noteparameter\c!height*\c_strc_notes_columns\relax\else\maxdimen\fi
- \global\skip \currentnoteins\s_strc_notes_distance}
+ \global\count\namedinsertionnumber\currentnote\numexpr\plusthousand/\c_strc_notes_columns\relax
+ \global\dimen\namedinsertionnumber\currentnote\ifnotelimit\dimexpr\noteparameter\c!height*\c_strc_notes_columns\relax\else\maxdimen\fi
+ \global\skip \namedinsertionnumber\currentnote\s_strc_notes_distance}
\def\strc_notes_set_location_columns
{\setfalse\c_strc_notes_delayed
@@ -970,26 +968,26 @@
\ifnum\currentnofcolumns=\zerocount
\c_strc_notes_columns\plusone
\fi
- \global\count\currentnoteins\numexpr\plusthousand/\c_strc_notes_columns\relax
- \global\dimen\currentnoteins\ifnotelimit\dimexpr\noteparameter\c!height*\c_strc_notes_columns\relax\else\maxdimen\fi
- \global\skip \currentnoteins\s_strc_notes_distance}
+ \global\count\namedinsertionnumber\currentnote\numexpr\plusthousand/\c_strc_notes_columns\relax
+ \global\dimen\namedinsertionnumber\currentnote\ifnotelimit\dimexpr\noteparameter\c!height*\c_strc_notes_columns\relax\else\maxdimen\fi
+ \global\skip \namedinsertionnumber\currentnote\s_strc_notes_distance}
\def\strc_notes_set_location_firstcolumn
{\setfalse\c_strc_notes_delayed
\strc_notes_set_distance
\strc_notes_set_columns
- \global\count\currentnoteins\plusthousand
- \global\dimen\currentnoteins\ifnotelimit\noteparameter\c!height\else\maxdimen\fi
- \global\skip \currentnoteins\s_strc_notes_distance}
+ \global\count\namedinsertionnumber\currentnote\plusthousand
+ \global\dimen\namedinsertionnumber\currentnote\ifnotelimit\noteparameter\c!height\else\maxdimen\fi
+ \global\skip \namedinsertionnumber\currentnote\s_strc_notes_distance}
\let\strc_notes_set_location_lastcolumn\strc_notes_set_location_firstcolumn
\def\strc_notes_set_location_text % we don't use inserts anyway (e.g. endnotes)
{\settrue\c_strc_notes_delayed
\ctxlua{structures.notes.setstate("\currentnote","store")}%
- \global\count\currentnoteins\zerocount
- \global\dimen\currentnoteins\maxdimen
- \global\skip \currentnoteins\zeropoint}
+ \global\count\namedinsertionnumber\currentnote\zerocount
+ \global\dimen\namedinsertionnumber\currentnote\maxdimen
+ \global\skip \namedinsertionnumber\currentnote\zeropoint}
\let\strc_notes_set_location_none\strc_notes_set_location_text
@@ -1013,7 +1011,7 @@
\newconditional\c_notes_bottom_present
\def\strc_notes_check_if_bottom_present_indeed % in otr !
- {\ifvoid\currentnoteins\else
+ {\ifvoid\namedinsertionnumber\currentnote\else
\strc_notes_set_position
\fi}
@@ -1134,7 +1132,7 @@
\strc_constructions_initialize{#1}%
\strc_notes_synchronize
\the\everybeforenoteinsert
- \insert\currentnoteins\bgroup
+ \insert\namedinsertionnumber\currentnote\bgroup
\the\everyinsidenoteinsert\relax
\doprocesslocalsetups{\noteparameter\c!setups}% experimental
\doifelse{\noteparameter\c!paragraph}\v!yes
@@ -1236,14 +1234,14 @@
\def\strc_notes_place_inserts
{\strc_notes_set_delayed % \strc_notes_synchronize % we need to know if it's delayed
\ifconditional\c_strc_notes_delayed \else
- \ifdim\ht\currentnoteins>\zeropoint % or a faster delayed test
+ \ifdim\ht\namedinsertionnumber\currentnote>\zeropoint % or a faster delayed test
\strc_notes_place_inserts_indeed
\fi
\fi}
\def\strc_notes_place_inserts_indeed
{\relax
- \ifdim\ht\currentnoteins>\zeropoint
+ \ifdim\ht\namedinsertionnumber\currentnote>\zeropoint
\endgraf
\ifvmode
\whitespace
@@ -1291,13 +1289,11 @@
\fi}
\def\strc_notes_flush_inserts_normal
- {%\iftrialtypesetting\copy\else\box\fi\currentnoteins
- \strc_notes_flush_global
+ {\strc_notes_flush_global
\obeydepth} % (a) added , since split footnotes will not align properly
\def\strc_notes_flush_inserts_columns
{\startsimplecolumns[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\noteparameter\c!width]%
- %\iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteins % compare with local
\strc_notes_flush_global
\stopsimplecolumns}
@@ -1313,18 +1309,15 @@
{\doifelse{\noteparameter\c!paragraph}\v!yes
{\vbox
{\beginofshapebox
- \iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteins
+ \iftrialtypesetting\unvcopied\else\unvboxed\fi\namedinsertionnumber\currentnote
\endofshapebox
- %\doreshapebox{\box\shapebox}{}{}{}% get rid of penalties etc
\let\strc_notes_between_paragraphs_indeed\strc_notes_between_paragraphs_first % shape works reverse
\doreshapebox
{\hbox{\unhbox\shapebox\strc_notes_between_paragraphs_indeed}}
- {}%
- {}%
- {}% get rid of penalties etc
+ \donothing \donothing \donothing % get rid of penalties etc
\innerflushshapebox
\convertvboxtohbox}}
- {\iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteins}}
+ {\iftrialtypesetting\unvcopied\else\unvboxed\fi\namedinsertionnumber\currentnote}}
%D Supporting end notes is surprisingly easy. Even better, we
%D can combine this feature with solving the common \TEX\
@@ -1358,7 +1351,7 @@
% we need a proper state: normal, postponing, flushing
-\def\postponenotes
+\unexpanded\def\postponenotes
{\ifconditional\postponingnotes\else
\global\settrue\postponingnotes
\global\let\flushnotes\doflushnotes
@@ -1367,7 +1360,7 @@
\let\flushnotes\relax
-\def\doflushnotes
+\unexpanded\def\doflushnotes
{\ifconditional\postponingnotes
\begingroup
\let\flushnotes \relax
@@ -1595,7 +1588,7 @@
\strc_notes_process\strc_notes_check_presence}
\def\strc_notes_check_presence
- {\ifdim\ht\currentnoteins>\zeropoint
+ {\ifdim\ht\namedinsertionnumber\currentnote>\zeropoint
\notespresenttrue
\fi}
@@ -1604,7 +1597,7 @@
% used in page-mul
- \ifdefined\currentnofcolumns\else \def\currentnofcolumns{\@@kln} \fi
+ \ifdefined\currentnofcolumns\else \def\currentnofcolumns{\nofcolumns} \fi
\unexpanded\def\fakenotes
{\ifhmode\endgraf\fi\ifvmode
@@ -1620,29 +1613,31 @@
\newdimen\totalnoteheight
- \def\doaddtototalnoteheight#1%
- {\ifdim\ht#1>\zeropoint
- \ifcase\count#1\else
- % todo: divide by count
- \advance\totalnoteheight\ht #1%
- \advance\totalnoteheight\skip#1%
+ \unexpanded\def\additionaltotalnoteheight#1% temp hacks anyway
+ {\dimexpr
+ \ifdim\ht#1>\zeropoint
+ \ifcase\count#1
+ \zeropoint
+ \else % todo: divide by count
+ \ht#1+\skip#1% hm, no stretch but a dimen anyway
+ \fi
+ \else
+ \zeropoint
\fi
- \fi}
+ \relax}
\def\docalculatetotalnoteheight
{\ifcase\c_strc_notes_page_location % tricky here ! ! ! to be sorted out ! ! !
- \doaddtototalnoteheight\currentnoteins
- \else
- % \doaddtototalnoteheight\currentbackupnoteins
+ \advance\totalnoteheight\normalexpanded{\additionaltotalnoteheight\namedinsertionnumber\currentnote}%
\fi}
\def\docalculatetotalclevernoteheight
{\ifcase\c_strc_notes_page_location \else % tricky here ! ! ! to be sorted out ! ! !
- \doaddtototalnoteheight\currentnoteins
+ \advance\totalnoteheight\normalexpanded{\additionaltotalnoteheight\namedinsertionnumber\currentnote}%
\fi}
\def\docalculatetotalpagenoteheight
- {\doaddtototalnoteheight\currentnoteins}
+ {\advance\totalnoteheight\normalexpanded{\additionaltotalnoteheight\namedinsertionnumber\currentnote}}
\def\calculatetotalnoteheight {\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalnoteheight}
\def\calculatetotalclevernoteheight{\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalclevernoteheight}
@@ -1670,7 +1665,7 @@
%D \stoptyping
% \def\dosynchronizenotes
-% {\ifvoid\currentnoteins\else\insert\currentnoteins{\unvbox\currentnoteins}\fi}
+% {\ifvoid\namedinsertionnumber\currentnote\else\insert\namedinsertionnumber\currentnote{\unvbox\namedinsertionnumber\currentnote}\fi}
%
% \def\synchronizenotes
% {\strc_notes_process\dosynchronizenotes}
diff --git a/tex/context/base/strc-reg.lua b/tex/context/base/strc-reg.lua
index 6da58345b..23609cfd9 100644
--- a/tex/context/base/strc-reg.lua
+++ b/tex/context/base/strc-reg.lua
@@ -266,6 +266,10 @@ local function preprocessentries(rawdata)
end
rawdata.entries = nil
end
+ local seeword = rawdata.seeword
+ if seeword then
+ seeword.processor, seeword.text = splitprocessor(seeword.text or "")
+ end
end
function registers.store(rawdata) -- metadata, references, entries
@@ -826,10 +830,11 @@ function registers.flush(data,options,prefixspec,pagespec)
context.startregisterseewords()
for i=1,nt do
local entry = t[i]
- local processor = entry.processors and entry.processors[1] or ""
+ local seeword = entry.seeword
+ local seetext = seeword.text or ""
+ local processor = seeword.processor or (entry.processors and entry.processors[1]) or ""
local seeindex = entry.references.seeindex or ""
- local seeword = entry.seeword.text or ""
- context.registerseeword(i,n,processor,0,seeindex,seeword)
+ context.registerseeword(i,n,processor,0,seeindex,seetext)
end
context.stopregisterseewords()
end
diff --git a/tex/context/base/strc-reg.mkiv b/tex/context/base/strc-reg.mkiv
index e90de80ec..973c6effd 100644
--- a/tex/context/base/strc-reg.mkiv
+++ b/tex/context/base/strc-reg.mkiv
@@ -332,7 +332,7 @@
\normalexpanded{\ctxlua{structures.registers.extend("\currentregister","\currentregisterlabel", {
metadata = {
\ifx\currentregisterownnumber\v!yes
- own = "\registerparameter\c!alternative", % can be used instead of pagenumber
+ own = "\registerparameter\c!alternative", % can be used instead of pagenumber
\fi
},
userdata = structures.helpers.touserdata(\!!bs\detokenize{#3}\!!es)
@@ -349,7 +349,8 @@
},
entries = {
% we need a special one for xml, this is just a single one
- \!!bs\currentregisterentries\!!es, \!!bs\currentregisterkeys\!!es
+ \!!bs\currentregisterentries\!!es,
+ \!!bs\currentregisterkeys\!!es
},
userdata = structures.helpers.touserdata(\!!bs\detokenize{#3}\!!es)
})
@@ -433,10 +434,11 @@
},
entries = {
% we need a special one for xml, this is just a single one
- "\currentregisterentries", "#2"
+ \!!bs\currentregisterentries\!!es,
+ \!!bs#2\!!es
},
seeword = {
- text = "\currentregisterseeword"
+ text = \!!bs\currentregisterseeword\!!es
},
}
}}%
diff --git a/tex/context/base/syst-aux.mkiv b/tex/context/base/syst-aux.mkiv
index 0571fd00f..bc75789bd 100644
--- a/tex/context/base/syst-aux.mkiv
+++ b/tex/context/base/syst-aux.mkiv
@@ -4702,12 +4702,12 @@
\let\syst_helpers_split_string\relax
-\def\beforesplitstring#1\at#2\to#3%
+\unexpanded\def\beforesplitstring#1\at#2\to#3%
{\def\syst_helpers_split_string##1#2##2#2##3\\%
{\def#3{##1}}%
\expandafter\syst_helpers_split_string#1#2#2\\}
-\def\aftersplitstring#1\at#2\to#3%
+\unexpanded\def\aftersplitstring#1\at#2\to#3%
{\def\syst_helpers_split_string##1#2##2@@@##3\\%
{\def#3{##2}}%
\expandafter\syst_helpers_split_string#1@@@#2@@@\\}
@@ -4717,7 +4717,7 @@
%D
%D A bonus macro.
-\def\splitstring#1\at#2\to#3\and#4%
+\unexpanded\def\splitstring#1\at#2\to#3\and#4%
{\def\syst_helpers_split_string##1#2##2\empty\empty\empty##3\\%
{\def#3{##1}%
\def\syst_helpers_split_string{##3}%
@@ -4728,7 +4728,7 @@
\fi}%
\expandafter\syst_helpers_split_string#1\empty\empty\empty#2\empty\empty\empty\\}
-\def\greedysplitstring#1\at#2\to#3\and#4%
+\unexpanded\def\greedysplitstring#1\at#2\to#3\and#4%
{\edef\asciib{#1}%
\let\asciic\asciib
\let#3\empty
@@ -4750,12 +4750,12 @@
%D aftertestandsplitstring,
%D testandsplitstring}
-\def\beforetestandsplitstring#1\at#2\to#3%
+\unexpanded\def\beforetestandsplitstring#1\at#2\to#3%
{\def\syst_helpers_split_string##1#2##2#2##3##4\\%
{\ifx##3\empty\let#3\empty\else\def#3{##1}\fi}%
\expandafter\syst_helpers_split_string#1#2#2\empty\\}
-\def\aftertestandsplitstring#1\at#2\to#3%
+\unexpanded\def\aftertestandsplitstring#1\at#2\to#3%
{\def\syst_helpers_split_string ##1#2##2@@@##3##4\\%
{\ifx##3\empty\let#3\empty\else\def#3{##2}\fi}%
\expandafter\syst_helpers_split_string #1@@@#2@@@\empty\\}
@@ -4776,7 +4776,7 @@
%D
%D Which in terms of \TEX\ looks like:
-\def\removesubstring#1\from#2\to#3%
+\unexpanded\def\removesubstring#1\from#2\to#3%
{\splitstring#2\to\m_syst_string_one\and\m_syst_string_two
\dodoglobal#3{\m_syst_string_one\m_syst_string_two}}
diff --git a/tex/context/base/trac-ctx.lua b/tex/context/base/trac-ctx.lua
new file mode 100644
index 000000000..dd3aa392a
--- /dev/null
+++ b/tex/context/base/trac-ctx.lua
@@ -0,0 +1,36 @@
+if not modules then modules = { } end modules ['trac-ctx'] = {
+ version = 1.001,
+ comment = "companion to trac-ctx.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+tex.trackers = tex.trackers or { }
+
+local textrackers = tex.trackers
+local register = trackers.register
+
+storage.register("tex/trackers",textrackers,"tex.trackers")
+
+local function doit(tag,v)
+ local tt = textrackers[tag]
+ if tt then
+ context.unprotect()
+ context(v and tt[1] or tt[2])
+ context.protect()
+ end
+end
+
+function commands.initializetextrackers()
+ for tag, commands in next, textrackers do
+ register(tag, function(v) doit(tag,v) end) -- todo: v,tag in caller
+ end
+end
+
+function commands.installtextracker(tag,enable,disable)
+ textrackers[tag] = { enable, disable }
+ register(tag, function(v) doit(tag,v) end) -- todo: v,tag in caller
+end
+
+-- lua.registerfinalizer(dump,"dump storage")
diff --git a/tex/context/base/trac-ctx.mkiv b/tex/context/base/trac-ctx.mkiv
new file mode 100644
index 000000000..4aeb99116
--- /dev/null
+++ b/tex/context/base/trac-ctx.mkiv
@@ -0,0 +1,28 @@
+
+%D \module
+%D [ file=trac-ctx,
+%D version=2012.07.13,
+%D title=\CONTEXT\ Tracing Macros,
+%D subtitle=TeX Trackers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Tracing Macros / TeX Trackers}
+
+\registerctxluafile{trac-ctx}{1.001}
+
+\unprotect
+
+\unexpanded\def\installtextracker#1#2#3%
+ {\ctxcommand{installtextracker("#1",\!!bs\detokenize{#2}\!!es,\!!bs\detokenize{#3}\!!es)}}
+
+\appendtoks
+ \ctxcommand{initializetextrackers()}%
+\to \everyjob
+
+\protect \endinput
diff --git a/tex/context/base/typo-txt.mkvi b/tex/context/base/typo-txt.mkvi
index 0e926ed2c..f1c80c1bd 100644
--- a/tex/context/base/typo-txt.mkvi
+++ b/tex/context/base/typo-txt.mkvi
@@ -105,10 +105,10 @@
\unexpanded\def\normalizefontdepth {\typo_normalizers_font_at_size\dp}
\unexpanded\def\normalizefontline {\typo_normalizers_font_at_size\htdp}
-\unexpanded\def\widthspanningtext #text#width#specification{\hbox{\normalizefontwidth \temp{#text}{#width}{#specification}\temp#text}}
-\unexpanded\def\heightspanningtext#text#width#specification{\hbox{\normalizefontheight\temp{#text}{#width}{#specification}\temp#text}}
-\unexpanded\def\depthspanningtext #text#width#specification{\hbox{\normalizefontdepth \temp{#text}{#width}{#specification}\temp#text}}
-\unexpanded\def\linespanningtext #text#width#specification{\hbox{\normalizefontline \temp{#text}{#width}{#specification}\temp#text}}
+\unexpanded\def\widthspanningtext #text#size#specification{\hbox{\normalizefontwidth \temp{#text}{#size}{#specification}\temp#text}}
+\unexpanded\def\heightspanningtext#text#size#specification{\hbox{\normalizefontheight\temp{#text}{#size}{#specification}\temp#text}}
+\unexpanded\def\depthspanningtext #text#size#specification{\hbox{\normalizefontdepth \temp{#text}{#size}{#specification}\temp#text}}
+\unexpanded\def\linespanningtext #text#size#specification{\hbox{\normalizefontline \temp{#text}{#size}{#specification}\temp#text}}
%D Traditionally we use UpperCasedNames for this kind of functionality.
diff --git a/tex/context/fonts/demo.lfg b/tex/context/fonts/demo.lfg
index 00ca3ee6e..06c59e644 100644
--- a/tex/context/fonts/demo.lfg
+++ b/tex/context/fonts/demo.lfg
@@ -30,11 +30,36 @@ return {
comment = "An example of goodies.",
author = "Hans Hagen",
featuresets = {
+ simple = {
+ mode = "node",
+ script = "latn"
+ },
default = {
- default,
+ mode = "node",
+ script = "latn",
+ kern = "yes",
+ },
+ ligatures = {
+ mode = "node",
+ script = "latn",
+ kern = "yes",
+ liga = "yes",
},
smallcaps = {
- default, smallcaps,
+ mode = "node",
+ script = "latn",
+ kern = "yes",
+ smcp = "yes",
+ },
+ },
+ solutions = { -- here we have references to featuresets, so we use strings!
+ experimental = {
+ less = {
+ "ligatures", "simple",
+ },
+ more = {
+ "smallcaps",
+ },
},
},
colorschemes = {
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index c69ac8a24..b92bf2ab3 100644
--- a/tex/generic/context/luatex/luatex-fonts-merged.lua
+++ b/tex/generic/context/luatex/luatex-fonts-merged.lua
@@ -1,6 +1,6 @@
-- merged file : luatex-fonts-merged.lua
-- parent file : luatex-fonts.lua
--- merge date : 07/10/12 00:56:44
+-- merge date : 07/17/12 00:23:01
do -- begin closure to overcome local limits and interference