diff --git a/luametalatex-back-pdf.lua b/luametalatex-back-pdf.lua index 092dad4..5b7bde8 100644 --- a/luametalatex-back-pdf.lua +++ b/luametalatex-back-pdf.lua @@ -143,10 +143,9 @@ callback.register("stop_run", function() texio.write_nl(string.format("Transcript written on %s.\n", status.log_name)) end, "Finish PDF file") token.luacmd("pdfvariable", function() - for n, t in pairs(pdf.variable_tokens) do + for _, n in ipairs(pdf.variable_names) do if token.scan_keyword(n) then - token.put_next(t) - return + return token.put_next(token.create('pdfvariable ' .. n)) end end -- The following error message gobbles the next word as a side effect. diff --git a/luametalatex-baseregisters.lua b/luametalatex-baseregisters.lua new file mode 100644 index 0000000..b06bb77 --- /dev/null +++ b/luametalatex-baseregisters.lua @@ -0,0 +1,99 @@ +local value_values = token.values'value' +for i=0,#value_values do + value_values[value_values[i]] = i +end +local count_code = value_values.integer +local dimen_code = value_values.dimension + +local set_local = require'luametalatex-local' + +local texmeta = getmetatable(tex) +local texmetaoldindex = texmeta.__index +local texmetaoldnewindex = texmeta.__newindex + +local tex_variables = {} + +function texmeta.__index(t, k) + return tex_variables[k] or texmetaoldindex(t, k) +end +function texmeta.__newindex(t, k, v) + if tex_variables[k] then + return set_local(tex_variables, k, v) + else + return texmetaoldnewindex(t, k, v) + end +end + +local function tex_variable(value, scanner, name, default) + token.luacmd(name, function(_, scanning) + if scanning == 'value' then + return value, tex_variables[name] + else + token.scan_keyword'=' + return set_local(tex_variables, name, scanner(), scanning == 'global') + end + end, 'global', 'protected', 'value') + tex_variables[name] = default +end + +local real_pdf_variables, pdf_variable_names = {}, {'pageresources'} +local pdf_toks = {} +local pdf_variables = setmetatable(pdf.variable, { + __index = function(_, k) + local v = real_pdf_variables[k] + if v then return v end + v = pdf_toks[k] + if v then + return tex.toks[v] + end + end, + __newindex = function(_, k, v) + if real_pdf_variables[k] then + return set_local(real_pdf_variables, k, v) + end + local toks = pdf_toks[k] + if toks then + tex.toks[toks] = v + end + end, +}) +pdf.variable_names = pdf_variable_names + +local function pdf_variable(value, scanner, name, default) + pdf_variable_names[#pdf_variable_names+1] = name + token.luacmd('pdfvariable ' .. name, function(_, scanning) + if scanning == 'value' then + return value, real_pdf_variables[name] + else + token.scan_keyword'=' + return set_local(real_pdf_variables, name, scanner(), scanning == 'global') + end + end, 'global', 'protected', 'value') + real_pdf_variables[name] = default +end + +tex_variable(count_code, token.scan_int, 'suppressfontnotfounderror', 0) +tex_variable(count_code, token.scan_int, 'outputmode', 1) -- The "traditional" default would be 0, + -- but we do not actually support that. +tex_variable(dimen_code, token.scan_dimen, 'pageheight', tex.sp'297mm') +tex_variable(dimen_code, token.scan_dimen, 'pagewidth', tex.sp'210mm') + +tex_variable(count_code, token.scan_int, 'bodydirection', 0) +tex_variable(count_code, token.scan_int, 'pagedirection', 0) + +pdf_variable(dimen_code, token.scan_dimen, 'horigin', tex.sp'1in') +pdf_variable(dimen_code, token.scan_dimen, 'vorigin', tex.sp'1in') +pdf_variable(dimen_code, token.scan_dimen, 'linkmargin', tex.sp'0pt') +pdf_variable(count_code, token.scan_int, 'majorversion', 1) +pdf_variable(count_code, token.scan_int, 'minorversion', 7) +pdf_variable(count_code, token.scan_int, 'compresslevel', 0) +pdf_variable(count_code, token.scan_int, 'objcompresslevel', 0) -- 0 is actually the only supported value right now, so this is basically ignored + +function tex.getbodydir() return tex.bodydirection end +function tex.getpagedir() return tex.pagedirection end +function tex.setbodydir(i) tex.bodydirection = i end +function tex.setpagedir(i) tex.pagedirection = i end +local dir_regs = require 'luametalatex-dir-registers' +dir_regs 'textdir' +dir_regs 'bodydir' +dir_regs 'pagedir' diff --git a/luametalatex-baseregisters.tex b/luametalatex-baseregisters.tex deleted file mode 100644 index cd6a01c..0000000 --- a/luametalatex-baseregisters.tex +++ /dev/null @@ -1,124 +0,0 @@ -\begingroup -\catcode`\^^^^fffe=11 -\catcode`\@=11 -\toks0{% - do - local function frozen(s) - local t = token.create(s) - return t - % print(t, token.new(t.mode, t.command), t.mode, t.command, t.data, t.cmdchrcs) - % return token.new(t.mode, t.command) - end - local dimen_cmd = token.command_id'register_dimen' - local count_cmd = token.command_id'register_int' - local toks_cmd = token.command_id'register_toks' - local tex_params = {} - local texmeta = getmetatable(tex) - local texmetaoldindex = texmeta.__index - local texmetaoldnewindex = texmeta.__newindex - function texmeta.__index(t, k) - local v = tex_params[k] - if v then - if v.command == count_cmd then - return tex.count[v.index] - elseif v.command == dimen_cmd then - return tex.dimen[v.index] - elseif v.command == toks_cmd then - return tex.toks[v.index] - end - else - return texmetaoldindex(t, k) - end - end - function texmeta.__newindex(t, k, v) - local p = tex_params[k] - if p then - if p.command == count_cmd then - tex.count[p.index] = v - elseif p.command == dimen_cmd then - tex.dimen[p.index] = v - elseif p.command == toks_cmd then - tex.toks[p.index] = v - end - else - return texmetaoldnewindex(t, k, v) - end - end - local pdf_params = {} - pdf.variable_tokens = pdf_params - setmetatable(pdf.variable, { - __index = function(t, k) - local v = pdf_params[k] - if v then - if v.command == count_cmd then - return tex.count[v.index] - elseif v.command == dimen_cmd then - return tex.dimen[v.index] - elseif v.command == toks_cmd then - return tex.toks[v.index] - end - end - end, - __newindex = function(t, k, v) - local p = pdf_params[k] - if p then - if p.command == count_cmd then - tex.count[p.index] = v - elseif p.command == dimen_cmd then - tex.dimen[p.index] = v - elseif p.command == toks_cmd then - tex.toks[p.index] = v - end - else - return rawset(t, k, v) - end - end, - }) -} -\def\InternalAlloc#1#2#3#4#5{% - \csname new#3\endcsname#1% - \global#1=#5\relax - \etoksapp0{#2_params["\luaescapestring{#4}"] = frozen"\luaescapestring{\csstring#1}"} -} -\def\internalAlloc#1#2#3{% - \expandafter\InternalAlloc\csname ^^^^fffe#3@#1\endcsname{#1}{#2}{#3}% -} -\def\texAlloc#1#2{% - \expandafter\InternalAlloc\csname #2\endcsname{tex}{#1}{#2}% -} -\def\pdfAlloc{% - \internalAlloc{pdf}% -} -\texAlloc{count}{suppressfontnotfounderror}{0} -\texAlloc{count}{outputmode}{1} % The "traditional" default would be 0, - % but we do not actually support that. -\texAlloc{dimen}{pageheight}{297mm} -\texAlloc{dimen}{pagewidth}{210mm} -\pdfAlloc{dimen}{horigin}{1in} -\pdfAlloc{dimen}{vorigin}{1in} -\pdfAlloc{dimen}{linkmargin}{0pt} -\pdfAlloc{count}{majorversion}{1} -\pdfAlloc{count}{minorversion}{7} -\pdfAlloc{count}{compresslevel}{0} -\pdfAlloc{count}{objcompresslevel}{0} % 0 is actually the only supported value right now, so this is basically ignored -\pdfAlloc{toks}{pageresources}{{}} - -\texAlloc{count}{bodydirection}{0} -\texAlloc{count}{pagedirection}{0} -\etoksapp0{ - function tex.getbodydir() return tex.bodydirection end - function tex.getpagedir() return tex.pagedirection end - function tex.setbodydir(i) tex.bodydirection = i end - function tex.setpagedir(i) tex.pagedirection = i end - local dir_regs = require 'luametalatex-dir-registers' - dir_regs 'textdir' - dir_regs 'bodydir' - dir_regs 'pagedir' - end -} - -\directlua{ - lua.prepared_code[\csstring#lua.prepared_code+1] = tex.toks[0] - \the\toks0 -} -\endgroup diff --git a/luametalatex-dir-registers.lua b/luametalatex-dir-registers.lua index f4b671d..2c4abcf 100644 --- a/luametalatex-dir-registers.lua +++ b/luametalatex-dir-registers.lua @@ -11,16 +11,13 @@ function tex.gettextdir() return tex.textdirection end function tex.getlinedir() return tex.linedirection end function tex.getmathdir() return tex.mathdirection end function tex.getpardir() return tex.pardirection end --- local integer_code = value_values.none local integer_code = value_values.integer -local functions = lua.get_functions_table() -local lua_call_cmd = token.command_id'lua_call' local function set_xdir(id, scanning) - -- local name = names[id] - if scanning then + if scanning == 'value' then + print(scanning) return integer_code, getters[id]() - -- return integer_code, tex[name .. 'ection'] end + -- local global = scanning == 'global' local value if token.scan_keyword'tlt' then value = 0 @@ -30,7 +27,6 @@ local function set_xdir(id, scanning) value = token.scan_int() end setters[id](value) - -- tex["set" .. name](value) end return function(name) local getter = tex["get" .. name] diff --git a/luametalatex-firstcode.lua b/luametalatex-firstcode.lua index c8650ad..33a97d5 100644 --- a/luametalatex-firstcode.lua +++ b/luametalatex-firstcode.lua @@ -12,7 +12,7 @@ local set_lua = token.set_lua -- probably doesn't store the function in the array part of the Lua table. -- Let's reconsider if this ever becomes a problem. -- local new_luafunction = luatexbase.new_luafunction -local predefined_luafunctions = status.ini_version and 65535 -- 1<<16 - 1 -- We start with 1<<16 +local predefined_luafunctions = status.ini_version and 65536 -- 1<<16 -- We start with 1<<16 + 1 (1<<16=65536 is reserved for luametalatex-local) local function new_luafunction(name) if predefined_luafunctions then predefined_luafunctions = predefined_luafunctions + 1 @@ -221,6 +221,7 @@ else -- fixupluafunctions = nil -- end end +require'luametalatex-baseregisters' require'luametalatex-back-pdf' require'luametalatex-node-luaotfload' diff --git a/luametalatex-local.lua b/luametalatex-local.lua new file mode 100644 index 0000000..488acb2 --- /dev/null +++ b/luametalatex-local.lua @@ -0,0 +1,53 @@ +-- Implement support for local variables. + +local stack = {} + +local restore_func = 65536 -- Reserved in firstcode +lua.get_functions_table()[restore_func] = function() + local level = assert(stack[tex.currentgrouplevel], 'Out of sync') + stack[tex.currentgrouplevel] = nil + for t,entries in next, level do + for k,v in next, entries do + t[k] = v + end + end +end +local lua_call = token.command_id'lua_call' +local restore_toks = {token.create'atendofgroup', token.new(restore_func, lua_call)} +local put_next = token.put_next +local runtoks = tex.runtoks +local function put_restore_toks() + put_next(restore_toks) +end + +return function(t, k, v, global) + local l = tex.currentgrouplevel + if global then + for i=1,l do + local level = stack[i] + if level then + local saved = level[t] + if saved then + saved[k] = nil + end + end + end + elseif l > 0 then + local level = stack[l] + if not level then + level = {} + runtoks(put_restore_toks) + stack[l] = level + end + + local saved = level[t] + if not saved then + saved = {} + level[t] = saved + end + + saved[k] = saved[k] or t[k] + end + + t[k] = v +end diff --git a/luametalatex-ltexpl-hook.tex b/luametalatex-ltexpl-hook.tex index 1c0f262..e619323 100644 --- a/luametalatex-ltexpl-hook.tex +++ b/luametalatex-ltexpl-hook.tex @@ -1,5 +1,6 @@ \directlua{unhook_expl()} -\input luametalatex-baseregisters +% See baseregisters for list of toks pdfvariables +\expandafter\newtoks\csname pdfvariable \space pageresources\endcsname \ifx\@tfor\undefined \def\@tfor#1\do#2{} \fi diff --git a/luametalatex-pdf-escape.lua b/luametalatex-pdf-escape.lua index 8d87fe1..4739a40 100644 --- a/luametalatex-pdf-escape.lua +++ b/luametalatex-pdf-escape.lua @@ -1,4 +1,4 @@ -local mode = 6 +local mode = 0 -- Control how much escaping is done... the mode is a bitset: -- Bit 0: Disable auto-detection of pre-escaped input -- Bit 1: Convert UTF-8 input to UTF-16 diff --git a/luametaplain.ini b/luametaplain.ini index 59616be..4cb69b2 100644 --- a/luametaplain.ini +++ b/luametaplain.ini @@ -17,5 +17,5 @@ \endgroup \input load-unicode-data.tex \input etex.src -\input luametalatex-baseregisters +\expandafter\newtoks\csname pdfvariable \space pageresources\endcsname \dump