summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/generic/babel/babel-bidi-basic.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/generic/babel/babel-bidi-basic.lua')
-rw-r--r--Master/texmf-dist/tex/generic/babel/babel-bidi-basic.lua371
1 files changed, 371 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/generic/babel/babel-bidi-basic.lua b/Master/texmf-dist/tex/generic/babel/babel-bidi-basic.lua
new file mode 100644
index 00000000000..c5104648763
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/babel/babel-bidi-basic.lua
@@ -0,0 +1,371 @@
+--
+-- This is file `babel-bidi-basic.lua',
+-- generated with the docstrip utility.
+--
+-- The original source files were:
+--
+-- babel.dtx (with options: `basic')
+--
+--
+-- Copyright (C) 2012-2018 Javier Bezos and Johannes L. Braams.
+-- Copyright (C) 1989-2012 Johannes L. Braams and
+-- any individual authors listed elsewhere in this file.
+-- All rights reserved.
+--
+-- This file is part of the Babel system.
+-- --------------------------------------
+--
+-- It may be distributed and/or modified under the
+-- conditions of the LaTeX Project Public License, either version 1.3
+-- of this license or (at your option) any later version.
+-- The latest version of this license is in
+-- http://www.latex-project.org/lppl.txt
+-- and version 1.3 or later is part of all distributions of LaTeX
+-- version 2003/12/01 or later.
+--
+-- This work has the LPPL maintenance status "maintained".
+--
+-- The Current Maintainer of this work is Javier Bezos.
+--
+-- The list of derived (unpacked) files belonging to the distribution
+-- and covered by LPPL is defined by the unpacking scripts (with
+-- extension |.ins|) which are part of the distribution.
+--
+Babel = Babel or {}
+
+Babel.fontmap = Babel.fontmap or {}
+Babel.fontmap[0] = {} -- l
+Babel.fontmap[1] = {} -- r
+Babel.fontmap[2] = {} -- al/an
+
+function Babel.pre_otfload_v(head)
+ -- head = Babel.numbers(head)
+ head = Babel.bidi(head, true)
+ return head
+end
+
+function Babel.pre_otfload_h(head, gc, sz, pt, dir)
+ -- head = Babel.numbers(head)
+ head = Babel.bidi(head, false, dir)
+ return head
+end
+
+require('babel-bidi.lua')
+
+local characters = Babel.characters
+local ranges = Babel.ranges
+
+local DIR = node.id('dir')
+local GLYPH = node.id('glyph')
+
+local function insert_implicit(head, state, outer)
+ local new_state = state
+ if state.sim and state.eim and state.sim ~= state.eim then
+ dir = ((outer == 'r') and 'TLT' or 'TRT') -- ie, reverse
+ local d = node.new(DIR)
+ d.dir = '+' .. dir
+ node.insert_before(head, state.sim, d)
+ local d = node.new(DIR)
+ d.dir = '-' .. dir
+ node.insert_after(head, state.eim, d)
+ end
+ new_state.sim, new_state.eim = nil, nil
+ return head, new_state
+end
+
+local function insert_numeric(head, state)
+ local new
+ local new_state = state
+ if state.san and state.ean and state.san ~= state.ean then
+ local d = node.new(DIR)
+ d.dir = '+TLT'
+ _, new = node.insert_before(head, state.san, d)
+ if state.san == state.sim then state.sim = new end
+ local d = node.new(DIR)
+ d.dir = '-TLT'
+ _, new = node.insert_after(head, state.ean, d)
+ if state.ean == state.eim then state.eim = new end
+ end
+ new_state.san, new_state.ean = nil, nil
+ return head, new_state
+end
+
+-- \hbox with an explicit dir can lead to wrong results
+-- <R \hbox dir TLT{<R>}> and <L \hbox dir TRT{<L>}>
+
+function Babel.bidi(head, ispar, hdir)
+ local d -- d is used mainly for computations in a loop
+ local prev_d = ''
+ local new_d = false
+
+ local nodes = {}
+ local outer_first = nil
+
+ local has_en = false
+ local first_et = nil
+
+ local ATDIR = luatexbase.registernumber'bbl@attr@dir'
+
+ local save_outer
+ local temp = node.get_attribute(head, ATDIR)
+ if temp then
+ temp = temp % 3
+ save_outer = (temp == 0 and 'l') or
+ (temp == 1 and 'r') or
+ (temp == 2 and 'al')
+ elseif ispar then -- Or error? Shouldn't happen
+ save_outer = ('TRT' == tex.pardir) and 'r' or 'l'
+ else
+ save_outer = ('TRT' == hdir) and 'r' or 'l'
+ end
+ local outer = save_outer
+ local last = outer
+ -- 'al' is only taken into account in the first, current loop
+ if save_outer == 'al' then save_outer = 'r' end
+
+ local fontmap = Babel.fontmap
+
+ for item in node.traverse(head) do
+
+ -- In what follows, #node is the last (previous) node, because the
+ -- current one is not added until we start processing the neutrals.
+
+ -- three cases: glyph, dir, otherwise
+ if item.id == GLYPH then
+
+ local chardata = characters[item.char]
+ d = chardata and chardata.d or nil
+ if not d then
+ for nn, et in ipairs(ranges) do
+ if item.char < et[1] then
+ break
+ elseif item.char <= et[2] then
+ d = et[3]
+ break
+ end
+ end
+ end
+ d = d or 'l'
+
+ local temp = (d == 'l' and 0) or
+ (d == 'r' and 1) or
+ (d == 'al' and 2) or
+ (d == 'an' and 2) or nil
+ if temp and fontmap and fontmap[temp][item.font] then
+ item.font = fontmap[temp][item.font]
+ end
+
+ if new_d then
+ table.insert(nodes, {nil, (outer == 'l') and 'l' or 'r', nil})
+ attr_d = node.get_attribute(item, ATDIR)
+ attr_d = attr_d % 3
+ if attr_d == 1 then
+ outer_first = 'r'
+ last = 'r'
+ elseif attr_d == 2 then
+ outer_first = 'r'
+ last = 'al'
+ else
+ outer_first = 'l'
+ last = 'l'
+ end
+ outer = last
+ has_en = false
+ first_et = nil
+ new_d = false
+ end
+
+ elseif item.id == DIR then
+ d = nil
+ new_d = true
+
+ else
+ d = nil
+ end
+
+ -- AL <= EN/ET/ES -- W2 + W3 + W6
+ if last == 'al' and d == 'en' then
+ d = 'an' -- W3
+ elseif last == 'al' and (d == 'et' or d == 'es') then
+ d = 'on' -- W6
+ end
+
+ -- EN + CS/ES + EN -- W4
+ if d == 'en' and #nodes >= 2 then
+ if (nodes[#nodes][2] == 'es' or nodes[#nodes][2] == 'cs')
+ and nodes[#nodes-1][2] == 'en' then
+ nodes[#nodes][2] = 'en'
+ end
+ end
+
+ -- AN + CS + AN -- W4 too, because uax9 mixes both cases
+ if d == 'an' and #nodes >= 2 then
+ if (nodes[#nodes][2] == 'cs')
+ and nodes[#nodes-1][2] == 'an' then
+ nodes[#nodes][2] = 'an'
+ end
+ end
+
+ -- ET/EN -- W5 + W7->l / W6->on
+ if d == 'et' then
+ first_et = first_et or (#nodes + 1)
+ elseif d == 'en' then
+ has_en = true
+ first_et = first_et or (#nodes + 1)
+ elseif first_et then -- d may be nil here !
+ if has_en then
+ if last == 'l' then
+ temp = 'l' -- W7
+ else
+ temp = 'en' -- W5
+ end
+ else
+ temp = 'on' -- W6
+ end
+ for e = first_et, #nodes do
+ if nodes[e][1].id == GLYPH then nodes[e][2] = temp end
+ end
+ first_et = nil
+ has_en = false
+ end
+
+ if d then
+ if d == 'al' then
+ d = 'r'
+ last = 'al'
+ elseif d == 'l' or d == 'r' then
+ last = d
+ end
+ prev_d = d
+ table.insert(nodes, {item, d, outer_first})
+ else
+ -- Not sure about the following. Looks too 'ad hoc', but it's
+ -- required for numbers, so that 89 19 becomes 19 89. It also
+ -- affects n+cs/es+n.
+ if prev_d == 'an' or prev_d == 'en' then
+ table.insert(nodes, {item, 'on', nil})
+ end
+ end
+
+ outer_first = nil
+
+ end
+
+ -- TODO -- repeated here in case EN/ET is the last node. Find a
+ -- better way of doing things:
+ if first_et then -- dir may be nil here !
+ if has_en then
+ if last == 'l' then
+ temp = 'l' -- W7
+ else
+ temp = 'en' -- W5
+ end
+ else
+ temp = 'on' -- W6
+ end
+ for e = first_et, #nodes do
+ if nodes[e][1].id == GLYPH then nodes[e][2] = temp end
+ end
+ end
+
+ -- dummy node, to close things
+ table.insert(nodes, {nil, (outer == 'l') and 'l' or 'r', nil})
+
+ --------------- NEUTRAL -----------------
+
+ outer = save_outer
+ last = outer
+
+ local first_on = nil
+
+ for q = 1, #nodes do
+ local item
+
+ local outer_first = nodes[q][3]
+ outer = outer_first or outer
+ last = outer_first or last
+
+ local d = nodes[q][2]
+ if d == 'an' or d == 'en' then d = 'r' end
+ if d == 'cs' or d == 'et' or d == 'es' then d = 'on' end --- W6
+
+ if d == 'on' then
+ first_on = first_on or q
+ elseif first_on then
+ if last == d then
+ temp = d
+ else
+ temp = outer
+ end
+ for r = first_on, q - 1 do
+ nodes[r][2] = temp
+ item = nodes[r][1] -- MIRRORING
+ if item.id == GLYPH and temp == 'r' then
+ item.char = characters[item.char].m or item.char
+ end
+ end
+ first_on = nil
+ end
+
+ if d == 'r' or d == 'l' then last = d end
+ end
+
+ -------------- IMPLICIT, REORDER ----------------
+
+ outer = save_outer
+ last = outer
+
+ local state = {}
+ state.has_r = false
+
+ for q = 1, #nodes do
+
+ local item = nodes[q][1]
+
+ outer = nodes[q][3] or outer
+
+ local d = nodes[q][2]
+
+ if d == 'nsm' then d = last end -- W1
+ if d == 'en' then d = 'an' end
+ local isdir = (d == 'r' or d == 'l')
+
+ if outer == 'l' and d == 'an' then
+ state.san = state.san or item
+ state.ean = item
+ elseif state.san then
+ head, state = insert_numeric(head, state)
+ end
+
+ if outer == 'l' then
+ if d == 'an' or d == 'r' then -- im -> implicit
+ if d == 'r' then state.has_r = true end
+ state.sim = state.sim or item
+ state.eim = item
+ elseif d == 'l' and state.sim and state.has_r then
+ head, state = insert_implicit(head, state, outer)
+ elseif d == 'l' then
+ state.sim, state.eim, state.has_r = nil, nil, false
+ end
+ else
+ if d == 'an' or d == 'l' then
+ state.sim = state.sim or item
+ state.eim = item
+ elseif d == 'r' and state.sim then
+ head, state = insert_implicit(head, state, outer)
+ elseif d == 'r' then
+ state.sim, state.eim = nil, nil
+ end
+ end
+
+ if isdir then
+ last = d -- Don't search back - best save now
+ elseif d == 'on' and state.san then
+ state.san = state.san or item
+ state.ean = item
+ end
+
+ end
+
+ return node.prev(head) or head
+end