Current File : //usr/share/texlive/texmf-dist/tex/generic/babel/babel-bidi-basic-r.lua |
--
-- This is file `babel-bidi-basic-r.lua',
-- generated with the docstrip utility.
--
-- The original source files were:
--
-- babel.dtx (with options: `basic-r')
--
--
-- Copyright (C) 2012-2021 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.bidi_enabled = true
require('babel-data-bidi.lua')
local characters = Babel.characters
local ranges = Babel.ranges
local DIR = node.id("dir")
local function dir_mark(head, from, to, outer)
dir = (outer == 'r') and 'TLT' or 'TRT' -- ie, reverse
local d = node.new(DIR)
d.dir = '+' .. dir
node.insert_before(head, from, d)
d = node.new(DIR)
d.dir = '-' .. dir
node.insert_after(head, to, d)
end
function Babel.bidi(head, ispar)
local first_n, last_n -- first and last char with nums
local last_es -- an auxiliary 'last' used with nums
local first_d, last_d -- first and last char in L/R block
local dir, dir_real
local strong = ('TRT' == tex.pardir) and 'r' or 'l'
local strong_lr = (strong == 'l') and 'l' or 'r'
local outer = strong
local new_dir = false
local first_dir = false
local inmath = false
local last_lr
local type_n = ''
for item in node.traverse(head) do
-- three cases: glyph, dir, otherwise
if item.id == node.id'glyph'
or (item.id == 7 and item.subtype == 2) then
local itemchar
if item.id == 7 and item.subtype == 2 then
itemchar = item.replace.char
else
itemchar = item.char
end
local chardata = characters[itemchar]
dir = chardata and chardata.d or nil
if not dir then
for nn, et in ipairs(ranges) do
if itemchar < et[1] then
break
elseif itemchar <= et[2] then
dir = et[3]
break
end
end
end
dir = dir or 'l'
if inmath then dir = ('TRT' == tex.mathdir) and 'r' or 'l' end
if new_dir then
attr_dir = 0
for at in node.traverse(item.attr) do
if at.number == luatexbase.registernumber'bbl@attr@dir' then
attr_dir = at.value % 3
end
end
if attr_dir == 1 then
strong = 'r'
elseif attr_dir == 2 then
strong = 'al'
else
strong = 'l'
end
strong_lr = (strong == 'l') and 'l' or 'r'
outer = strong_lr
new_dir = false
end
if dir == 'nsm' then dir = strong end -- W1
dir_real = dir -- We need dir_real to set strong below
if dir == 'al' then dir = 'r' end -- W3
if strong == 'al' then
if dir == 'en' then dir = 'an' end -- W2
if dir == 'et' or dir == 'es' then dir = 'on' end -- W6
strong_lr = 'r' -- W3
end
elseif item.id == node.id'dir' and not inmath then
new_dir = true
dir = nil
elseif item.id == node.id'math' then
inmath = (item.subtype == 0)
else
dir = nil -- Not a char
end
if dir == 'en' or dir == 'an' or dir == 'et' then
if dir ~= 'et' then
type_n = dir
end
first_n = first_n or item
last_n = last_es or item
last_es = nil
elseif dir == 'es' and last_n then -- W3+W6
last_es = item
elseif dir == 'cs' then -- it's right - do nothing
elseif first_n then -- & if dir = any but en, et, an, es, cs, inc nil
if strong_lr == 'r' and type_n ~= '' then
dir_mark(head, first_n, last_n, 'r')
elseif strong_lr == 'l' and first_d and type_n == 'an' then
dir_mark(head, first_n, last_n, 'r')
dir_mark(head, first_d, last_d, outer)
first_d, last_d = nil, nil
elseif strong_lr == 'l' and type_n ~= '' then
last_d = last_n
end
type_n = ''
first_n, last_n = nil, nil
end
if dir == 'l' or dir == 'r' then
if dir ~= outer then
first_d = first_d or item
last_d = item
elseif first_d and dir ~= strong_lr then
dir_mark(head, first_d, last_d, outer)
first_d, last_d = nil, nil
end
end
if dir and not last_lr and dir ~= 'l' and outer == 'r' then
item.char = characters[item.char] and
characters[item.char].m or item.char
elseif (dir or new_dir) and last_lr ~= item then
local mir = outer .. strong_lr .. (dir or outer)
if mir == 'rrr' or mir == 'lrr' or mir == 'rrl' or mir == 'rlr' then
for ch in node.traverse(node.next(last_lr)) do
if ch == item then break end
if ch.id == node.id'glyph' and characters[ch.char] then
ch.char = characters[ch.char].m or ch.char
end
end
end
end
if dir == 'l' or dir == 'r' then
last_lr = item
strong = dir_real -- Don't search back - best save now
strong_lr = (strong == 'l') and 'l' or 'r'
elseif new_dir then
last_lr = nil
end
end
if last_lr and outer == 'r' then
for ch in node.traverse_id(node.id'glyph', node.next(last_lr)) do
if characters[ch.char] then
ch.char = characters[ch.char].m or ch.char
end
end
end
if first_n then
dir_mark(head, first_n, last_n, outer)
end
if first_d then
dir_mark(head, first_d, last_d, outer)
end
return node.prev(head) or head
end