summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/mkiv/typo-dub.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkiv/typo-dub.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-dub.lua271
1 files changed, 173 insertions, 98 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-dub.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-dub.lua
index f27e4047660..d0747ae6ccd 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/typo-dub.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-dub.lua
@@ -55,6 +55,8 @@ local mirrordata = characters.mirrors
local textclassdata = characters.textclasses
local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
local getnext = nuts.getnext
local getid = nuts.getid
@@ -63,11 +65,11 @@ local getlist = nuts.getlist
local getchar = nuts.getchar
local getattr = nuts.getattr
local getprop = nuts.getprop
-local getdirection = nuts.getdirection
+local getdir = nuts.getdir
local setprop = nuts.setprop
local setchar = nuts.setchar
-local setdirection = nuts.setdirection
+local setdir = nuts.setdir
local setattrlist = nuts.setattrlist
local remove_node = nuts.remove
@@ -75,10 +77,10 @@ local insert_node_after = nuts.insert_after
local insert_node_before = nuts.insert_before
local nodepool = nuts.pool
-local new_direction = nodepool.direction
+local new_textdir = nodepool.textdir
local nodecodes = nodes.nodecodes
-local gluecodes = nodes.gluecodes
+local skipcodes = nodes.skipcodes
local glyph_code = nodecodes.glyph
local glue_code = nodecodes.glue
@@ -87,29 +89,24 @@ local vlist_code = nodecodes.vlist
local math_code = nodecodes.math
local dir_code = nodecodes.dir
local localpar_code = nodecodes.localpar
+local parfillskip_code = skipcodes.parfillskip
-local parfillskip_code = gluecodes.parfillskip
-
-local dirvalues = nodes.dirvalues
-local lefttoright_code = dirvalues.lefttoright
-local righttoleft_code = dirvalues.righttoleft
-
-local maximum_stack = 0xFF
-
-local a_directions = attributes.private('directions')
+local maximum_stack = 0xFF -- unicode: 60, will be jumped to 125, we don't care too much
local directions = typesetters.directions
local setcolor = directions.setcolor
local getfences = directions.getfences
+local a_directions = attributes.private('directions')
+
local remove_controls = true directives.register("typesetters.directions.removecontrols",function(v) remove_controls = v end)
----- analyze_fences = true directives.register("typesetters.directions.analyzefences", function(v) analyze_fences = v end)
-local report_directions = logs.reporter("typesetting","directions three")
+local trace_directions = false trackers .register("typesetters.directions.two", function(v) trace_directions = v end)
+local trace_details = false trackers .register("typesetters.directions.two.details", function(v) trace_details = v end)
+local trace_list = false trackers .register("typesetters.directions.two.list", function(v) trace_list = v end)
-local trace_directions = false trackers.register("typesetters.directions", function(v) trace_directions = v end)
-local trace_details = false trackers.register("typesetters.directions.details", function(v) trace_details = v end)
-local trace_list = false trackers.register("typesetters.directions.list", function(v) trace_list = v end)
+local report_directions = logs.reporter("typesetting","directions two")
-- strong (old):
--
@@ -120,7 +117,7 @@ local trace_list = false trackers.register("typesetters.directions.list
-- lre : left to right embedding
-- rle : left to left embedding
-- al : right to legt arabic (esp punctuation issues)
---
+
-- weak:
--
-- en : english number
@@ -130,23 +127,23 @@ local trace_list = false trackers.register("typesetters.directions.list
-- cs : common number separator
-- nsm : nonspacing mark
-- bn : boundary neutral
---
+
-- neutral:
--
-- b : paragraph separator
-- s : segment separator
-- ws : whitespace
-- on : other neutrals
---
+
-- interesting: this is indeed better (and more what we expect i.e. we already use this split
-- in the old original (also these isolates)
---
+
-- strong (new):
--
-- l : left to right
-- r : right to left
-- al : right to left arabic (esp punctuation issues)
---
+
-- explicit: (new)
--
-- lro : left to right override
@@ -209,28 +206,27 @@ end
local function show_done(list,size)
local joiner = utfchar(0x200C)
local result = { }
- local format = formatters["<%s>"]
for i=1,size do
local entry = list[i]
local character = entry.char
local begindir = entry.begindir
local enddir = entry.enddir
if begindir then
- result[#result+1] = format(begindir)
+ result[#result+1] = formatters["<%s>"](begindir)
end
if entry.remove then
-- continue
elseif character == 0xFFFC then
- result[#result+1] = format("?")
+ result[#result+1] = formatters["<%s>"]("?")
elseif character == 0x0020 then
- result[#result+1] = format(" ")
+ result[#result+1] = formatters["<%s>"](" ")
elseif character >= 0x202A and character <= 0x202C then
- result[#result+1] = format(entry.original)
+ result[#result+1] = formatters["<%s>"](entry.original)
else
result[#result+1] = utfchar(character)
end
if enddir then
- result[#result+1] = format(enddir)
+ result[#result+1] = formatters["<%s>"](enddir)
end
end
return concat(result,joiner)
@@ -240,7 +236,17 @@ end
-- char is only used for mirror, so in fact we can as well only store it for
-- glyphs only
-local function build_list(head)
+-- using metatable is slightly faster so maybe some day ...
+
+-- local space = { char = 0x0020, direction = "ws", original = "ws" }
+-- local lre = { char = 0x202A, direction = "lre", original = "lre" }
+-- local rle = { char = 0x202B, direction = "rle", original = "rle" }
+-- local pdf = { char = 0x202C, direction = "pdf", original = "pdf" }
+-- local object = { char = 0xFFFC, direction = "on", original = "on" }
+--
+-- local t = { level = 0 } setmetatable(t,space) list[size] = t
+
+local function build_list(head) -- todo: store node pointer ... saves loop
-- P1
local current = head
local list = { }
@@ -276,19 +282,13 @@ local function build_list(head)
list[size] = { char = 0x0020, direction = "ws", original = "ws", level = 0 }
current = getnext(current)
elseif id == dir_code then
- local direction, pop = getdirection(current)
- if direction == lefttoright_code then
- if pop then
- list[size] = { char = 0x202C, direction = "pdf", original = "pdf", level = 0 }
- else
- list[size] = { char = 0x202A, direction = "lre", original = "lre", level = 0 }
- end
- elseif direction == righttoleft_code then
- if pop then
- list[size] = { char = 0x202C, direction = "pdf", original = "pdf", level = 0 }
- else
- list[size] = { char = 0x202B, direction = "rle", original = "rle", level = 0 }
- end
+ local dir = getdir(current)
+ if dir == "+TLT" then
+ list[size] = { char = 0x202A, direction = "lre", original = "lre", level = 0 }
+ elseif dir == "+TRT" then
+ list[size] = { char = 0x202B, direction = "rle", original = "rle", level = 0 }
+ elseif dir == "-TLT" or dir == "-TRT" then
+ list[size] = { char = 0x202C, direction = "pdf", original = "pdf", level = 0 }
else
list[size] = { char = 0xFFFC, direction = "on", original = "on", level = 0, id = id } -- object replacement character
end
@@ -343,8 +343,8 @@ end
local function resolve_fences(list,size,start,limit)
-- N0: funny effects, not always better, so it's an option
- local stack = { }
- local nofstack = 0
+ local stack = { }
+ local top = 0
for i=start,limit do
local entry = list[i]
if entry.direction == "on" then
@@ -355,15 +355,15 @@ local function resolve_fences(list,size,start,limit)
entry.mirror = mirror
entry.class = class
if class == "open" then
- nofstack = nofstack + 1
- stack[nofstack] = { mirror, i, false }
- elseif nofstack == 0 then
+ top = top + 1
+ stack[top] = { mirror, i, false }
+ elseif top == 0 then
-- skip
elseif class == "close" then
- while nofstack > 0 do
- local stacktop = stack[nofstack]
- if stacktop[1] == char then
- local open = stacktop[2]
+ while top > 0 do
+ local s = stack[top]
+ if s[1] == char then
+ local open = s[2]
local close = i
list[open ].paired = close
list[close].paired = open
@@ -371,7 +371,7 @@ local function resolve_fences(list,size,start,limit)
else
-- do we mirror or not
end
- nofstack = nofstack - 1
+ top = top - 1
end
end
end
@@ -394,32 +394,27 @@ end
-- the action
-local function get_baselevel(head,list,size,direction)
- if direction == lefttoright_code or direction == righttoleft_code then
- return direction, true
- elseif getid(head) == localpar_code and getsubtype(head) == 0 then
- direction = getdirection(head)
- if direction == lefttoright_code or direction == righttoleft_code then
- return direction, true
+local function get_baselevel(head,list,size) -- todo: skip if first is object (or pass head and test for localpar)
+ local id = getid(head)
+ if id == localpar_code then
+ if getdir(head) == "TRT" then
+ return 1, "TRT", true
+ else
+ return 0, "TLT", true
end
- end
- -- for old times sake we we handle strings too
- if direction == "TLT" then
- return lefttoright_code, true
- elseif direction == "TRT" then
- return righttoleft_code, true
- end
- -- P2, P3
- for i=1,size do
- local entry = list[i]
- local direction = entry.direction
- if direction == "r" or direction == "al" then -- and an ?
- return righttoleft_code, true
- elseif direction == "l" then
- return lefttoright_code, true
+ else
+ -- P2, P3
+ for i=1,size do
+ local entry = list[i]
+ local direction = entry.direction
+ if direction == "r" or direction == "al" then -- and an ?
+ return 1, "TRT", true
+ elseif direction == "l" then
+ return 0, "TLT", true
+ end
end
+ return 0, "TLT", false
end
- return lefttoright_code, false
end
local function resolve_explicit(list,size,baselevel)
@@ -485,17 +480,16 @@ local function resolve_explicit(list,size,baselevel)
end
-- X7
elseif direction == "pdf" then
- if nofstack > 0 then
+ if nofstack < maximum_stack then
local stacktop = stack[nofstack]
+ nofstack = nofstack - 1
level = stacktop[1]
override = stacktop[2]
- nofstack = nofstack - 1
entry.level = level
entry.direction = "bn"
entry.remove = true
elseif trace_directions then
- report_directions("stack underflow at position %a with direction %a",
- i, direction)
+ report_directions("stack overflow at position %a with direction %a",i,direction)
end
-- X6
else
@@ -694,6 +688,33 @@ local function resolve_neutral(list,size,start,limit,orderbefore,orderafter)
end
end
+-- local function resolve_implicit(list,size,start,limit,orderbefore,orderafter)
+-- -- I1
+-- for i=start,limit do
+-- local entry = list[i]
+-- local level = entry.level
+-- if level % 2 ~= 1 then -- not odd(level)
+-- local direction = entry.direction
+-- if direction == "r" then
+-- entry.level = level + 1
+-- elseif direction == "an" or direction == "en" then
+-- entry.level = level + 2
+-- end
+-- end
+-- end
+-- -- I2
+-- for i=start,limit do
+-- local entry = list[i]
+-- local level = entry.level
+-- if level % 2 == 1 then -- odd(level)
+-- local direction = entry.direction
+-- if direction == "l" or direction == "en" or direction == "an" then
+-- entry.level = level + 1
+-- end
+-- end
+-- end
+-- end
+
local function resolve_implicit(list,size,start,limit,orderbefore,orderafter,baselevel)
for i=start,limit do
local entry = list[i]
@@ -793,6 +814,52 @@ local function resolve_levels(list,size,baselevel,analyze_fences)
end
end
+-- local function insert_dir_points(list,size)
+-- -- L2, but no actual reversion is done, we simply annotate where
+-- -- begindir/endddir node will be inserted.
+-- local maxlevel = 0
+-- local finaldir = false
+-- for i=1,size do
+-- local level = list[i].level
+-- if level > maxlevel then
+-- maxlevel = level
+-- end
+-- end
+-- for level=0,maxlevel do
+-- local started = false
+-- local begindir = nil
+-- local enddir = nil
+-- if level % 2 == 1 then
+-- begindir = "+TRT"
+-- enddir = "-TRT"
+-- else
+-- begindir = "+TLT"
+-- enddir = "-TLT"
+-- end
+-- for i=1,size do
+-- local entry = list[i]
+-- if entry.level >= level then
+-- if not started then
+-- entry.begindir = begindir
+-- started = true
+-- end
+-- else
+-- if started then
+-- list[i-1].enddir = enddir
+-- started = false
+-- end
+-- end
+-- end
+-- -- make sure to close the run at end of line
+-- if started then
+-- finaldir = enddir
+-- end
+-- end
+-- if finaldir then
+-- list[size].enddir = finaldir
+-- end
+-- end
+
local function insert_dir_points(list,size)
-- L2, but no actual reversion is done, we simply annotate where
-- begindir/endddir node will be inserted.
@@ -810,12 +877,12 @@ local function insert_dir_points(list,size)
local enddir -- = nil
local prev -- = nil
if toggle then
- begindir = lefttoright_code
- enddir = lefttoright_code
+ begindir = "+TLT"
+ enddir = "-TLT"
toggle = false
else
- begindir = righttoleft_code
- enddir = righttoleft_code
+ begindir = "+TRT"
+ enddir = "-TRT"
toggle = true
end
for i=1,size do
@@ -855,7 +922,7 @@ local function insert_dir_points(list,size)
if trace_list and n > 1 then
report_directions("unbalanced list")
end
- last.enddir = s[n] == righttoleft_code and righttoleft_code or lefttoright_code
+ last.enddir = s[n] == "+TRT" and "-TRT" or "-TLT"
end
end
end
@@ -863,6 +930,7 @@ end
local function apply_to_list(list,size,head,pardir)
local index = 1
local current = head
+ local done = false
if trace_list then
report_directions("start run")
end
@@ -896,31 +964,34 @@ local function apply_to_list(list,size,head,pardir)
setcolor(current,direction,false,mirror)
end
elseif id == hlist_code or id == vlist_code then
- setdirection(current,pardir) -- is this really needed?
+ setdir(current,pardir) -- is this really needed?
elseif id == glue_code then
if enddir and getsubtype(current) == parfillskip_code then
-- insert the last enddir before \parfillskip glue
- local d = new_direction(enddir,true)
- -- setprop(d,"directions",true)
+ local d = new_textdir(enddir)
+ setprop(d,"directions",true)
-- setattrlist(d,current)
head = insert_node_before(head,current,d)
enddir = false
+ done = true
end
elseif begindir then
- if id == localpar_code and getsubtype(current) == 0 then
+ if id == localpar_code then
-- localpar should always be the 1st node
- local d = new_direction(begindir)
- -- setprop(d,"directions",true)
+ local d = new_textdir(begindir)
+ setprop(d,"directions",true)
-- setattrlist(d,current)
head, current = insert_node_after(head,current,d)
begindir = nil
+ done = true
end
end
if begindir then
- local d = new_direction(begindir)
- -- setprop(d,"directions",true)
+ local d = new_textdir(begindir)
+ setprop(d,"directions",true)
-- setattrlist(d,current)
head = insert_node_before(head,current,d)
+ done = true
end
local skip = entry.skip
if skip and skip > 0 then
@@ -930,16 +1001,18 @@ local function apply_to_list(list,size,head,pardir)
end
end
if enddir then
- local d = new_direction(enddir,true)
- -- setprop(d,"directions",true)
+ local d = new_textdir(enddir)
+ setprop(d,"directions",true)
-- setattrlist(d,current)
head, current = insert_node_after(head,current,d)
+ done = true
end
if not entry.remove then
current = getnext(current)
elseif remove_controls then
-- X9
head, current = remove_node(head,current,true)
+ done = true
else
current = getnext(current)
end
@@ -948,16 +1021,17 @@ local function apply_to_list(list,size,head,pardir)
if trace_list then
report_directions("stop run")
end
- return head
+ return head, done
end
-local function process(head,direction,only_one,where)
+local function process(head)
+ head = tonut(head)
-- for the moment a whole paragraph property
local attr = getattr(head,a_directions)
local analyze_fences = getfences(attr)
--
local list, size = build_list(head)
- local baselevel, dirfound = get_baselevel(head,list,size,direction)
+ local baselevel, pardir, dirfound = get_baselevel(head,list,size) -- we always have an inline dir node in context
if not dirfound and trace_details then
report_directions("no initial direction found, gambling")
end
@@ -971,7 +1045,8 @@ local function process(head,direction,only_one,where)
report_directions("after : %s",show_list(list,size,"direction"))
report_directions("result : %s",show_done(list,size))
end
- return apply_to_list(list,size,head,baselevel)
+ local head, done = apply_to_list(list,size,head,pardir)
+ return tonode(head), done
end
directions.installhandler(interfaces.variables.two,process)