summaryrefslogtreecommitdiff
path: root/tex/context/base/attr-ini.lua
blob: ad40816815b4b4f564136b8838508e4e00c5f4fa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
if not modules then modules = { } end modules ['attr-ini'] = {
    version   = 1.001,
    comment   = "companion to attr-ini.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

local commands, context, nodes, storage = commands, context, nodes, storage

local next, type = next, type

--[[ldx--
<p>We start with a registration system for atributes so that we can use the
symbolic names later on.</p>
--ldx]]--

attributes            = attributes or { }
local attributes      = attributes

local sharedstorage   = storage.shared

local texgetcount     = tex.getcount
local texsetattribute = tex.setattribute

attributes.names      = attributes.names    or { }
attributes.numbers    = attributes.numbers  or { }
attributes.list       = attributes.list     or { }
attributes.states     = attributes.states   or { }
attributes.handlers   = attributes.handlers or { }
attributes.unsetvalue = -0x7FFFFFFF

local names           = attributes.names
local numbers         = attributes.numbers
local list            = attributes.list

storage.register("attributes/names",   names,   "attributes.names")
storage.register("attributes/numbers", numbers, "attributes.numbers")
storage.register("attributes/list",    list,    "attributes.list")

function attributes.define(name,number) -- at the tex end
    if not numbers[name] then
        numbers[name] = number
        names[number] = name
        list[number]  = { }
    end
end

--[[ldx--
<p>We reserve this one as we really want it to be always set (faster).</p>
--ldx]]--

names[0], numbers["fontdynamic"] = "fontdynamic", 0

--[[ldx--
<p>We can use the attributes in the range 127-255 (outside user space). These
are only used when no attribute is set at the \TEX\ end which normally
happens in <l n='context'/>.</p>
--ldx]]--

sharedstorage.attributes_last_private = sharedstorage.attributes_last_private or 127

-- to be considered (so that we can use an array access):
--
-- local private = { } attributes.private = private
--
-- setmetatable(private, {
--     __index = function(t,name)
--         local number = sharedstorage.attributes_last_private
--         if number < 1023 then -- texgetcount("minallocatedattribute") - 1
--             number = number + 1
--             sharedstorage.attributes_last_private = number
--         end
--         numbers[name], names[number], list[number] = number, name, { }
--         private[name] = number
--         return number
--     end,
--     __call = function(t,name)
--         return t[name]
--     end
-- } )

function attributes.private(name) -- at the lua end (hidden from user)
    local number = numbers[name]
    if not number then
        local last = sharedstorage.attributes_last_private
        if last < 1023 then -- texgetcount("minallocatedattribute") - 1
            last = last + 1
            sharedstorage.attributes_last_private = last
        else
            report_attribute("no more room for private attributes")
            os.exit()
        end
        number = last
        numbers[name], names[number], list[number] = number, name, { }
    end
    return number
end

-- tracers

local report_attribute = logs.reporter("attributes")

local function showlist(what,list)
    if list then
        local a = list.next
        local i = 0
        while a do
            local number, value = a.number, a.value
            i = i + 1
            report_attribute("%S %2i: attribute %3i, value %4i, name %a",what,i,number,value,names[number])
            a = a.next
        end
   end
end

function attributes.showcurrent()
    showlist("current",node.current_attr())
end

function attributes.ofnode(n)
    showlist(n,n.attr)
end

-- interface

commands.defineattribute = attributes.define
commands.showattributes  = attributes.showcurrent

function commands.getprivateattribute(name)
    context(attributes.private(name))
end

-- rather special

local store = { }

function commands.savecurrentattributes(name)
    name = name or ""
    local n = node.current_attr()
    n = n and n.next
    local t = { }
    while n do
        t[n.number] = n.value
        n = n.next
    end
    store[name] = {
        attr = t,
        font = font.current(),
    }
end

function commands.restorecurrentattributes(name)
    name = name or ""
    local t = store[name]
    if t then
        local attr = t.attr
        local font = t.font
        if attr then
            for k, v in next, attr do
                texsetattribute(k,v)
            end
        end
        if font then
         -- tex.font = font
            context.getvalue(fonts.hashes.csnames[font]) -- we don't have a direct way yet (will discuss it with taco)
        end
    end
 -- store[name] = nil
end