summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/luatex/luavlna/luavlna.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/luatex/luavlna/luavlna.lua')
-rw-r--r--Master/texmf-dist/tex/luatex/luavlna/luavlna.lua316
1 files changed, 316 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/luatex/luavlna/luavlna.lua b/Master/texmf-dist/tex/luatex/luavlna/luavlna.lua
new file mode 100644
index 00000000000..ce596bc2588
--- /dev/null
+++ b/Master/texmf-dist/tex/luatex/luavlna/luavlna.lua
@@ -0,0 +1,316 @@
+-- Module luavlna
+-- code originally created by Patrick Gundlach
+-- http://tex.stackexchange.com/q/27780/2891
+-- The code was adapted for plain TeX and added some more features
+-- 1. It is possible to turn this functionality only for some letters
+-- 2. Code now works even for single letters after brackets etc.
+--
+local M = {}
+local utf_match = unicode.utf8.match
+local utf_char = unicode.utf8.char
+local utf_len = unicode.utf8.len
+
+local glue_id = node.id "glue"
+local glyph_id = node.id "glyph"
+local hlist_id = node.id "hlist"
+local vlist_id = node.id "vlist"
+local math_id = node.id "math"
+local period_char = string.byte(".")
+
+local alpha = string.char(37).."a" -- alpha class, entering
+-- percent char directly caused error
+local alphas = {}
+local match_char = function(x) return utf_match(x,alpha) end
+local match_table = function(x, chars)
+ local chars=chars or {}
+ return chars[x]
+end
+local singlechars = {} -- {a=true,i=true,z=true, v=true, u=true, o = true}
+
+local initials = {}
+
+local main_language = nil
+
+-- when main_language is set, we will not use lang info in the nodes, but
+-- main language instead
+local get_language = function(lang)
+ return main_language or lang
+end
+
+local set_main_language = function(lang)
+ main_language = lang
+end
+
+local debug = false
+local tex4ht = false
+-- Enable processing only for certain letters
+-- must be table in the {char = true, char2=true} form
+local set_singlechars= function(lang,c)
+ --print("Set single chars lua")
+ print(type(lang), lang)
+ if type(lang) == "table" then
+ for _,l in pairs(lang) do
+ print("language: ",l)
+ singlechars[l] = c
+ end
+ else
+ local lang = tonumber(lang)
+ print("language: ",lang)
+ -- for k,_ in pairs(c) do print(k) end
+ singlechars[lang] = c
+ end
+end
+
+local set_initials = function(lang,c)
+ if type(lang) == "table" then
+ for _,l in pairs(lang) do
+ initials[l] = c
+ end
+ else
+ local lang = tonumber(lang)
+ initials[lang]=c
+ end
+end
+
+
+local debug_tex4ht = function(head,p)
+ --[[ local w = node.new("glyph")
+ w.lang = tex.lang
+ w.font = font.current()
+ w.char = 64
+ ]]
+ --node.remove(head,node.prev(p))
+ local w = node.new("whatsit", "special")
+ w.data = "t4ht=<span style='background-color:red;width:2pt;'> </span>"
+ return w, head
+end
+
+local debug_node = function(head,p)
+ local w
+ if tex4ht then
+ w, head = debug_tex4ht(head,p)
+ else
+ w = node.new("whatsit","pdf_literal")
+ w.data = "q 1 0 1 RG 1 0 1 rg 0 0 m 0 5 l 2 5 l 2 0 l b Q"
+ end
+ node.insert_after(head,head,w)
+ node.insert_after(head,w,p)
+ -- return w
+end
+
+
+local set_debug= function(x)
+ debug = x
+end
+
+local set_tex4ht = function()
+ tex4ht = true
+end
+
+local insert_penalty = function(head)
+ local p = node.new("penalty")
+ p.penalty = 10000
+ local debug = debug or false
+ if debug then
+ local w = debug_node(head,p)
+ else
+ node.insert_after(head,head,p)
+ end
+ return head
+end
+
+local replace_with_thin_space = function(head)
+ local gluenode = node.new(node.id("glue"))
+ local gluespec = node.new(node.id("glue_spec"))
+ gluenode.width = tex.sp("0.2em")
+ -- gluenode.spec = gluespec
+ gluenode.next = head.next
+ gluenode.prev = head.prev
+ gluenode.next.prev = gluenode
+ gluenode.prev.next = gluenode
+ return gluenode
+end
+
+local is_alpha = function(c)
+ local status = alphas[c]
+ if not status then
+ status = utf_match(c, alpha)
+ alphas[c] = status
+ end
+ return status
+end
+
+-- find whether letter is uppercase
+local up_table = {}
+local is_uppercase= function(c)
+ if not is_alpha(c) then return false end
+ local status = up_table[c]
+ if status ~= nil then
+ return status
+ end
+ status = unicode.utf8.upper(c) == c
+ up_table[c] = status
+ return status
+end
+
+local is_number = function(word)
+ return tonumber(string.sub(word, -1)) ~= nil
+end
+
+local init_buffer = ""
+local is_initial = function(c, lang)
+ return is_uppercase(c)
+end
+
+local cut_off_end_chars = function(word, dot)
+ local last = string.sub(word, -1)
+ while word ~= "" and (not dot or last ~= ".") and not is_alpha(last) do
+ word = string.sub(word, 1, -2) -- remove last char
+ last = string.sub(word, -1)
+ end
+ return word
+end
+
+local part_until_non_alpha = function(word)
+ for i = 1, #word do
+ local c = word:sub(i,i)
+ if not is_alpha(c) then
+ word = string.sub(word, 1, i-1)
+ break
+ end
+ end
+ return word
+end
+
+
+function Set (list)
+ local set = {}
+ for _, l in ipairs(list) do set[l] = true end
+ return set
+end
+
+
+local presi = (require "luavlna-presi")
+local si = Set(require "luavlna-si")
+
+local is_unit = function(word)
+ if M.no_unit==true then return false end
+ word = part_until_non_alpha(word)
+ if si[word] then
+ return true
+ end
+ for _, prefix in pairs(presi) do
+ s, e = string.find(word, prefix)
+ if s == 1 then
+ local unit = string.sub(word, e+1)
+ if si[unit] then
+ return true
+ end
+ end
+ end
+ return false
+end
+
+local predegrees = Set (require "luavlna-predegrees")
+local sufdegrees = Set (require "luavlna-sufdegrees")
+
+local function prevent_single_letter (head)
+ local singlechars = singlechars -- or {}
+ -- match_char matches all single letters, but this method is abbandoned
+ -- in favor of using table with enabled letters. With this method, multiple
+ -- languages are supported
+ local test_fn = match_table -- singlechars and match_table or match_char
+ local space = true
+ local init = false
+ local anchor = head
+ local wasnumber = false
+ local word = ""
+ local no_predegrees = M.no_predegrees
+ local no_sufdegrees = M.no_sufdegrees
+ local in_math = false
+ while head do
+ local id = head.id
+ local nextn = head.next
+ local skip = node.has_attribute(head, luatexbase.attributes.preventsinglestatus)
+ if id == math_id then
+ if head.subtype == 0 then
+ word = ""
+ in_math = true
+ else
+ in_math = false
+ if is_number(word) then wasnumber = true end
+ word = ""
+ end
+ end
+ if skip ~= 1 and not in_math then
+ if id == glue_id then
+ if wasnumber then
+ if word ~= "" then
+ wasnumber = false
+ word = cut_off_end_chars(word, false)
+ if is_unit(word) then
+ anchor = replace_with_thin_space(anchor)
+ insert_penalty(anchor.prev)
+ end
+ end
+ elseif is_number(word) then
+ wasnumber = true
+ else
+ word = cut_off_end_chars(word, true)
+ if no_predegrees ~= true and predegrees[word] then
+ insert_penalty(head.prev)
+ elseif no_sufdegrees ~= true and sufdegrees[word] then
+ insert_penalty(anchor.prev)
+ end
+ end
+ space=true
+ anchor = head
+ word = ""
+ init = is_initial " " -- reset initials
+ elseif space==true and id == glyph_id and is_alpha(utf_char(head.char)) then -- a letter
+ local lang = get_language(head.lang)
+ local char = utf_char(head.char)
+ word = char
+ init = is_initial(char,lang)
+ local s = singlechars[lang] or {} -- load singlechars for node's lang
+ --[[
+ for k, n in pairs(singlechars) do
+ for c,_ in pairs(n) do
+ --print(type(k), c)
+ end
+ end
+ --]]
+ if test_fn(char, s) and nextn ~= nil and nextn.id == glue_id then -- only if we are at a one letter word
+ head = insert_penalty(head)
+ end
+ space = false
+ -- handle initials
+ -- uppercase letter followed by period (code 46)
+ elseif init and head.id == glyph_id and head.char == period_char and nextn.id == glue_id and utf_len(word) == 1 then
+ head = insert_penalty(head)
+ elseif head.id == glyph_id then
+ local char = utf_char(head.char)
+ word = word .. char
+ init = is_initial(char, head.lang)
+ -- hlist support
+ elseif head.id == hlist_id then
+ prevent_single_letter(head.head)
+ -- vlist support
+ elseif head.id == vlist_id then
+ prevent_single_letter(head.head)
+ end
+ elseif id == glyph_id and in_math then
+ word = word .. utf_char(head.char)
+ end
+ head = head.next
+ end
+ return true
+end
+
+M.preventsingle = prevent_single_letter
+M.singlechars = set_singlechars
+M.initials = set_initials
+M.set_tex4ht = set_tex4ht
+M.debug = set_debug
+M.set_main_language = set_main_language
+return M