% \iffalse meta-comment
%
% Copyright (C) 2009 by Elie Roux <elie.roux@telecom-bretagne.eu>
%
% This work is under the CC0 license.
%
% This work consists of the main source file luatextra.dtx
% and the derived files
%    luatextra.sty, luatextra.lua, luatextra-latex.tex, luatextra.pdf.
%
% Unpacking:
%    tex luatextra.dtx
%
% Documentation:
%    pdflatex luatextra.dtx
%
%    The class ltxdoc loads the configuration file ltxdoc.cfg
%    if available. Here you can specify further options, e.g.
%    use A4 as paper format:
%       \PassOptionsToClass{a4paper}{article}
%
%
%
%<*ignore>
\begingroup
  \def\x{LaTeX2e}%
\expandafter\endgroup
\ifcase 0\ifx\install y1\fi\expandafter
         \ifx\csname processbatchFile\endcsname\relax\else1\fi
         \ifx\fmtname\x\else 1\fi\relax
\else\csname fi\endcsname
%</ignore>
%<*install>
\input docstrip.tex

\keepsilent
\askforoverwritefalse

\let\MetaPrefix\relax

\preamble
This is a generated file.

Copyright (C) 2009 by Elie Roux <elie.roux@telecom-bretagne.eu>

This work is under the CC0 license.

This work consists of the main source file luainputenc.dtx
and the derived files
    luatextra.sty, luatextra.lua, luatextra-latex.tex, luatextra.pdf

\endpreamble

\let\MetaPrefix\DoubleperCent


\generate{%
  \usedir{tex/luatex/luatextra}%
  \file{luatextra.sty}{\from{luatextra.dtx}{package}}%
  \file{luatextra-latex.tex}{\from{luatextra.dtx}{latex}}%
}

% The following hacks are to generate a lua file with lua comments starting by
% -- instead of %%

\def\MetaPrefix{-- }

\def\luapostamble{%
  \MetaPrefix^^J%
  \MetaPrefix\space End of File `\outFileName'.%
}

\def\currentpostamble{\luapostamble}%

\generate{%
  \usedir{tex/luatex/luatextra}%
  \file{luatextra.lua}{\from{luatextra.dtx}{lua}}%%
}

\obeyspaces
\Msg{************************************************************************}
\Msg{*}
\Msg{* To finish the installation you have to move the following}
\Msg{* files into a directory searched by TeX:}
\Msg{*}
\Msg{*     luatextra.sty luatextra-latex.tex luatextra.lua}
\Msg{*}
\Msg{* Happy TeXing!}
\Msg{*}
\Msg{************************************************************************}

\endbatchfile
%</install>
%<*ignore>
\fi
%</ignore>
%<*driver>
\NeedsTeXFormat{LaTeX2e}
\ProvidesFile{luatextra.drv}%
  [2010/05/10 v0.97 LuaTeX extra low-level macros.]%
\documentclass{ltxdoc}
\EnableCrossrefs
\CodelineIndex
\begin{document}
  \DocInput{luatextra.dtx}%
\end{document}
%</driver>
% \fi
%
% \CheckSum{0}
%
% \CharacterTable
%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
%   Digits        \0\1\2\3\4\5\6\7\8\9
%   Exclamation   \!     Double quote  \"     Hash (number) \#
%   Dollar        \$     Percent       \%     Ampersand     \&
%   Acute accent  \'     Left paren    \(     Right paren   \)
%   Asterisk      \*     Plus          \+     Comma         \,
%   Minus         \-     Point         \.     Solidus       \/
%   Colon         \:     Semicolon     \;     Less than     \<
%   Equals        \=     Greater than  \>     Question mark \?
%   Commercial at \@     Left bracket  \[     Backslash     \\
%   Right bracket \]     Circumflex    \^     Underscore    \_
%   Grave accent  \`     Left brace    \{     Vertical bar  \|
%   Right brace   \}     Tilde         \~}
%
% \GetFileInfo{luatextra.drv}
%
% \title{The \textsf{luatextra} package}
% \date{2010/05/10 v0.97}
% \author{Elie Roux \\ \texttt{elie.roux@telecom-bretagne.eu}}
%
% \maketitle
%
% \begin{abstract}
% This document is made for people wanting to understand how the package was
% made. For an introduction to the use of Lua\TeX\ with the formats Plain and
% \LaTeX , please read the document \texttt{luatextra-reference.pdf} that you
% can find in your \TeX\ distribution (\TeX Live from version 2009) or on the
% CTAN.
%
% \textbf{Warning.} This package is undergoing major changes, so the
% documentation may sometimes be inconsistent. Also, be aware that everything
% may change.
% \end{abstract}
%
% \tableofcontents
%
% \section{\texttt{luatextra.lua}}
%
% \subsection{Initialization and internal functions}
%
% \iffalse
%<*lua>
% \fi
%
%    We create the \texttt{luatextra} table that will contain all the
%    functions and variables, and we register it as a normal lua module.
%
%    \begin{macrocode}
module("luatextra", package.seeall)
%    \end{macrocode}
%
%    We initiate the modules table that will contain informations about the
%    loaded modules. And we register the \texttt{luatextra} module. The
%    informations contained in the table describing the module are always the
%    same, it can be taken as a template. See
%    \texttt{luatextra.provides\_module} for more details.
%
%    \begin{macrocode}
luatexbase.provides_module {
    version     = 0.97,
    name        = "luatextra",
    date        = "2010/05/10",
    description = "Additional low level functions for LuaTeX",
    author      = "Elie Roux and Manuel Pegourie-Gonnard",
    copyright   = "Elie Roux, 2009 and Manuel Pegourie-Gonnard, 2010",
    license     = "CC0",
}
local format = string.format
%    \end{macrocode}
%
%    \subsection{Multiple callbacks on the \texttt{open\_read\_file}
%    callback\label{sub:orf}}
%
%    |luatexbase| (see documentation for details) cannot really provide a
%    simple and reliable way of registering multiple functions in some
%    callbacks. To be able to do so, the solution we implemented is to
%    register one function in these callbacks, and to create "sub-callbacks"
%    that can accept several functions. That's what we do here for the
%    callback \texttt{open\_read\_file}.
%
%    \begin{macro}{luatextra.open read file}
%
%    This function is the one that will be registered in the callback. It
%    calls new callbacks, that will be created later. These callbacks are:
%
%    \begin{itemize}
%    \item \texttt{pre\_read\_file} in which you can register a function with
%    the signature \texttt{pre\_read\_file(env)}, with \texttt{env} being a
%    table containing the fields \texttt{filename} which is the argument of
%    the callback \texttt{open\_read\_file}, and \texttt{path} which is the
%    result of \texttt{kpse.find\_file}. You can put any field you want in the
%    \texttt{env} table, you can even override the existing fields. This
%    function is called at the very beginning of the callback, it allows for
%    instance to register functions in the other callbacks. It is useless to
%    add a field \texttt{reader} or \texttt{close}, as they will be overriden.
%    \item \texttt{file\_reader} is automatically registered in the
%    \texttt{reader} callback for every file, it has the same signature.
%    \item \texttt{file\_close} is registered in the \texttt{close} callback
%    for every file, and has the same signature.
%    \end{itemize}
%
%    \begin{macrocode}
function luatextra.open_read_file(filename)
    local path = kpse.find_file(filename)
    local env = {
      ['filename'] = filename,
      ['path'] = path,
    }
    luatexbase.call_callback('pre_read_file', env)
    path = env.path
    if not path then
        return
    end
    local f = env.file
    if not f then
        f = io.open(path)
        env.file = f
    end
    if not f then
        return
    end
    env.reader = luatextra.reader
    env.close = luatextra.close
    return env
end
%    \end{macrocode}
%
% \end{macro}
%
%    The two next functions are the one called in the
%    \texttt{open\_read\_file} callback.
%
%    \begin{macrocode}
function luatextra.reader(env)
    local line = (env.file):read()
    line = luatexbase.call_callback('file_reader', env, line)
    return line
end
function luatextra.close(env)
    (env.file):close()
    luatexbase.call_callback('file_close', env)
end
%    \end{macrocode}
%
%    In the callback creation process we need to have default behaviours. Here
%    they are. These are called only when no function is registered in the
%    created callback. See the documentation of \texttt{luatexbase} for
%    more details.
%
%    \begin{macrocode}
function luatextra.default_reader(env, line)
    return line
end
function luatextra.default_close(env)
    return
end
function luatextra.default_pre_read(env)
    return env
end
%    \end{macrocode}
%
%    \subsection{Multiple callbacks on the \texttt{define\_font}
%    callback\label{sub:df}}
%
%    The same principle is applied to the \texttt{define\_font} callback. The
%    main difference is that this mechanism is not applied by default. The
%    reason is that the callback most people will register in the
%    \texttt{define\_font} callback is the one from Con\TeX t allowing the use
%    of OT fonts. When the code will be more adapted (not so soon certainly),
%    this mechanism will certainly be used, as it allows more flexibility in
%    the font syntax, the OT font load mechanism, etc.
%
%    The callbacks we register here are the following ones:
%
%    \begin{itemize}
%    \item \texttt{font\_syntax} that takes a table with the fields
%    \texttt{asked\_name}, \texttt{name} and \texttt{size}, and modifies this
%    table to add more information. It must add at least a \texttt{path}
%    field. The structure of the final table is not precisely defined, as it
%    can vary from one syntax to another.
%    \item \texttt{open\_otf\_font} takes the previous table, and must return
%    a valid font structure as described in the Lua\TeX\ manual.
%    \item \texttt{post\_font\_opening} takes the final font table and can
%    modify it, before this table is returned to the \texttt{define\_font}
%    callback.
%    \end{itemize}
%
%    But first, we acknowledge the fact that \texttt{fontforge} has been
%    renamed to \texttt{fontloader}. This check allows older versions of
%    Lua\TeX\ to use \texttt{fontloader}.
%
%    As this mechanism is not loaded by default and certainly won't be until
%    version 1.0 of Lua\TeX , we don't document it further. See the
%    documentation of \texttt{luatextra.sty} (macro
%    \texttt{\string\ltxtra\string@RegisterFontCallback}) to know how to load
%    this mechanism anyway.
%
%    \begin{macrocode}
do
  if tex.luatexversion < 36 then
      fontloader = fontforge
  end
end
function luatextra.find_font(name)
    local types = {'ofm', 'ovf', 'opentype fonts', 'truetype fonts'}
    local path = kpse.find_file(name)
    if path then return path end
    for _,t in pairs(types) do
        path = kpse.find_file(name, t)
        if path then return path end
    end
    return nil
end
function luatextra.font_load_error(error)
    luatextra.module_warning('luatextra', string.format('%s\nloading lmr10 instead...', error))
end
function luatextra.load_default_font(size)
    return font.read_tfm("lmr10", size)
end
function luatextra.define_font(name, size)
    if (size < 0) then size = (- 655.36) * size end
    local fontinfos = {
        asked_name = name,
        name = name,
        size = size
        }
    callback.call('font_syntax', fontinfos)
    name = fontinfos.name
    local path = fontinfos.path
    if not path then
        path = luatextra.find_font(name)
        fontinfos.path = luatextra.find_font(name)
    end
    if not path then
        luatextra.font_load_error("unable to find font "..name)
        return luatextra.load_default_font(size)
    end
    if not fontinfos.filename then
        fontinfos.filename = fpath.basename(path)
    end
    local ext = fpath.suffix(path)
    local f
    if ext == 'tfm' or ext == 'ofm' then
        f =  font.read_tfm(name, size)
    elseif ext == 'vf' or ext == 'ovf' then
        f =  font.read_vf(name, size)
    elseif ext == 'ttf' or ext == 'otf' or ext == 'ttc' then
        f = luatexbase.call_callback('open_otf_font', fontinfos)
    else
        luatextra.font_load_error("unable to determine the type of font "..name)
        f = luatextra.load_default_font(size)
    end
    if not f then
        luatextra.font_load_error("unable to load font "..name)
        f = luatextra.load_default_font(size)
    end
    luatexbase.call_callback('post_font_opening', f, fontinfos)
    return f
end
function luatextra.default_font_syntax(fontinfos)
    return
end
function luatextra.default_open_otf(fontinfos)
    return nil
end
function luatextra.default_post_font(f, fontinfos)
    return true
end
function luatextra.register_font_callback()
    luatexbase.add_to_callback('define_font', luatextra.define_font, 'luatextra.define_font')
end
%    \end{macrocode}
%
%    Initialise a few callbacks.
%
%    \begin{macrocode}
    luatexbase.create_callback('pre_read_file', 'simple', luatextra.default_pre_read)
    luatexbase.create_callback('file_reader', 'data', luatextra.default_reader)
    luatexbase.create_callback('file_close', 'simple', luatextra.default_close)
    luatexbase.add_to_callback('open_read_file', luatextra.open_read_file, 'luatextra.open_read_file')
    luatexbase.create_callback('font_syntax', 'simple', luatextra.default_font_syntax)
    luatexbase.create_callback('open_otf_font', 'first', luatextra.default_open_otf)
    luatexbase.create_callback('post_font_opening', 'simple', luatextra.default_post_font)
%    \end{macrocode}
% \iffalse
%</lua>
% \fi
%
% \section{\texttt{luatextra.sty}}
%
% \iffalse
%<*package>
% \fi
%
%    \subsection{Initializations}
%
%    First we prevent multiple loads of the file (useful for plain-\TeX ).
%
%    \begin{macrocode}
\csname ifluatextraloaded\endcsname
\let\ifluatextraloaded\endinput

%    \end{macrocode}
%
%    Then we load \textsf{ifluatex}.
%
%    \begin{macrocode}

\expandafter\ifx\csname ProvidesPackage\endcsname\relax
  \expandafter\ifx\csname ifluatex\endcsname\relax
    \input ifluatex.sty
  \fi
\else
  \RequirePackage{ifluatex}
  \NeedsTeXFormat{LaTeX2e}
  \ProvidesPackage{luatextra}
    [2010/05/10 v0.97 LuaTeX extra low-level macros]
\fi

%    \end{macrocode}
%
%    The two macros \texttt{\string\LuaTeX} and \texttt{\string\LuaLaTeX} are
%    defined to Lua\TeX\ and Lua\LaTeX , because that's the way it's written
%    in the Lua\TeX 's manual (not in small capitals).
%
%    These two macros are the only two loaded if we are under a non-Lua\TeX{}
%    engine.
%
%    \begin{macrocode}

\def\LuaTeX{Lua\TeX }
\def\LuaLaTeX{Lua\LaTeX }

%    \end{macrocode}
%
%    Make sure Lua\TeX\ is being used.
%
%    \begin{macrocode}
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname RequirePackage\endcsname\relax
  \input ifluatex.sty
\else
  \RequirePackage{ifluatex}
\fi
\ifluatex\else
  \begingroup
    \expandafter\ifx\csname PackageWarningNoLine\endcsname\relax
      \def\x#1#2{\begingroup\newlinechar10
        \immediate\write16{Package #1 warning: #2}\endgroup}
    \else
      \let\x\PackageWarningNoLine
    \fi
  \expandafter\endgroup
  \x{luatexbase-modutils}{LuaTeX is required for this package.^^J
    Aborting package loading.}
  \expandafter\endinput
\fi
%    \end{macrocode}
%
%    Load other usefull packages.
%
%    \begin{macrocode}
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname RequirePackage\endcsname\relax
  \input luatexbase-modutils.sty
  \input luatexbase-attr.sty
  \input luatexbase-cctb.sty
  \input luatexbase-regs.sty
  \input luatexbase-mcb.sty
\else
  \RequirePackage{luatexbase-modutils}
  \RequirePackage{luatexbase-attr}
  \RequirePackage{luatexbase-cctb}
  \RequirePackage{luatexbase-regs}
  \RequirePackage{luatexbase-mcb}
\fi
\luatexUseModule{lualibs}
%    \end{macrocode}
%
%    If the package is loaded with \LaTeX , we
%    also define the environment \texttt{luacode}.
%
%    \begin{macrocode}
\expandafter\ifx\csname RequirePackage\endcsname\relax \else
  \RequirePackage{environ}
  \NewEnviron{luacode}{\directlua{\BODY}}
\fi
%    \end{macrocode}
%
%
% \subsection{Primitives renaming}
%
%    Here we differenciate two very different cases: Lua\TeX\ version < 0.36
%    has no \texttt{tex.enableprimitives} function, and has support for
%    multiple lua states, and for versions > 0.35, the
%    \texttt{tex.enableprimitives} is provided, and the old
%    \texttt{\string\directlua} syntax prints a warning.
%
%    \begin{macrocode}
\ifnum\luatexversion<36
%    \end{macrocode}
%
%    For old versions, we simply rename the primitives. You can note that
%    \texttt{\string\attribute} (and also others) have no
%    \texttt{\string\primitive} before them, because it would make users
%    unable to call \texttt{\string\global\string\luaattribute}, which is a
%    strong restriction. With this method, we can call it, but if
%    \texttt{\string\attribute} was defined before, this means that
%    \texttt{\string\luaattribute} will get its meaning, which is dangerous.
%    Note also that you cannot use multiple states.
%
%    \begin{macrocode}
  \def\directlua{\pdfprimitive\directlua0}
  \def\latelua{\pdfprimitive\latelua0}
  \def\luadirect{\pdfprimitive\directlua0}
  \def\lualate{\pdfprimitive\latelua0}
  \def\luatexattribute{\attribute}
  \def\luatexattributedef{\attributedef}
  \def\luatexclearmarks{\pdfprimitive\luaclearmarks}
  \def\luatexformatname{\pdfprimitive\formatname}
  \def\luatexscantexttokens{\pdfprimitive\scantexttokens}
  \def\luatexcatcodetable{\catcodetable}
  \def\initluatexcatcodetable{\pdfprimitive\initcatcodetable}
  \def\saveluatexcatcodetable{\pdfprimitive\savecatcodetable}
  \def\luaclose{\pdfprimitive\closelua}
\else
%    \end{macrocode}
%
%    From TeXLive 2009, all primitives should be provided with the |luatex|
%    prefix. For TeXLive 2008, we provide some primitives with this prefix too,
%    to keep backward compatibility.
%
%    \begin{macrocode}
  \directlua{tex.enableprimitives('luatex', {'attribute'})}
  \directlua{tex.enableprimitives('luatex', {'attributedef'})}
  \directlua{tex.enableprimitives('luatex', {'clearmarks'})}
  \directlua{tex.enableprimitives('luatex', {'formatname'})}
  \directlua{tex.enableprimitives('luatex', {'scantexttokens'})}
  \directlua{tex.enableprimitives('luatex', {'catcodetable'})}
  \directlua{tex.enableprimitives('luatex', {'latelua'})}
  \directlua{tex.enableprimitives('luatex', {'initcatcodetable'})}
  \directlua{tex.enableprimitives('luatex', {'savecatcodetable'})}
  \directlua{tex.enableprimitives('luatex', {'closelua'})}
  \let\luadirect\directlua
  \let\lualate\luatexlatelua
  \let\initluatexcatcodetable\luatexinitcatcodetable
  \let\saveluatexcatcodetable\luatexsavecatcodetable
  \let\luaclose\luatexcloselua
\fi
%    \end{macrocode}
%
%    We load the \texttt{lua} file.
%
%    \begin{macrocode}
\directlua{dofile(kpse.find_file("luatextra.lua"))}
%    \end{macrocode}
%
%    A small macro to register the \texttt{define\_font} callback from
%    \textsf{luatextra}. See section \ref{sub:df} for more details.
%
%    \begin{macrocode}
\def\ltxtra@RegisterFontCallback{
  \directlua{luatextra.register_font_callback()}
}
%    \end{macrocode}
%
%    We provide some functions for backward compatibility with old versions of
%    luatextra.
%
%    \begin{macrocode}
\let\newluaattribute\newluatexattribute
\let\luaattribute\luatexattribute
\let\unsetluaattribute\unsetluatexattribute
\let\initluacatcodetable\initluatexcatcodetable
\let\luasetcatcoderange\luatexsetcatcoderange
\let\newluacatcodetable\newluatexcatcodetable
\let\setluaattribute\setluatexattribute
\let\luaModuleError\luatexModuleError
\let\luaRequireModule\luatexRequireModule
\let\luaUseModule\luatexUseModule
%    \end{macrocode}
%
%    Finally, we load \textsf{luaotfload}.
%
%    \begin{macrocode}
\expandafter\ifx\csname ProvidesPackage\endcsname\relax
  \input luaotfload.sty
\else
  \RequirePackage{luaotfload}
\fi
%    \end{macrocode}
% \iffalse
%</package>
% \fi
%
%
% \Finale
\endinput
