scrn-wid.lua /size: 10 Kb    last modification: 2021-10-28 13:50
1if not modules then modules = { } end modules ['scrn-wid'] = {
2    version   = 1.001,
3    comment   = "companion to scrn-wid.mkiv",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9-- Support for interactive features is handled elsewhere. Now that is some mess! In
10-- the early days one had media features like sound and movies that were easy to set
11-- up. Then at some point renditions came around which were more work and somewhat
12-- unreliable. Now, both mechanism are obsolete and replaced by rich media which is
13-- a huge mess and has no real concept of what media are supported. There's flash
14-- cq. shockwave (basically obsolete too), and for instance mp4 needs to be handled
15-- by a swf player, and there's u3d which somehow has its own specification. One
16-- would expect native support for video and audio to be en-par with browsers but
17-- alas ... pdf has lost the battle with html here due to a few decades of
18-- unstability and changing support. So far we could catch on and even were ahead
19-- but I wonder if we should keep doing that. As we can't trust support for media we
20-- can better not embed anything and just use a hyperlink to an external resource. No
21-- sane person will create media rich pdf's as long as it's that unpredictable. Just
22-- look at the specification and viewer preferences and decide.
23
24local next = next
25
26interactions             = interactions or { }
27local interactions       = interactions
28
29local context            = context
30local implement          = interfaces.implement
31
32local allocate           = utilities.storage.allocate
33
34local attachments        = allocate()
35local comments           = allocate()
36local soundclips         = allocate()
37local renderings         = allocate()
38local linkedlists        = allocate()
39
40interactions.attachments = attachments
41interactions.soundclips  = soundclips
42interactions.renderings  = renderings
43interactions.linkedlists = linkedlists
44
45local texsetbox          = tex.setbox
46
47local jobpasses          = job.passes
48
49local texgetcount        = tex.getcount
50
51local codeinjections     = backends.codeinjections
52local nodeinjections     = backends.nodeinjections
53
54local variables          = interfaces.variables
55local v_auto             = variables.auto
56
57local trace_attachments = false  trackers.register("widgets.attachments", function(v) trace_attachments = v end)
58
59local report_attachments = logs.reporter("widgets","attachments")
60
61-- Symbols
62
63implement {
64    name      = "presetsymbollist",
65    arguments = "string",
66    actions   = function(list)
67        codeinjections.presetsymbollist(list)
68    end
69}
70
71-- Attachments
72--
73-- registered : unique id
74-- tag        : used at the tex end
75-- file       : name that the file has on the filesystem
76-- name       : name that the file will get in the output
77-- title      : up to the backend
78-- subtitle   : up to the backend
79-- author     : up to the backend
80-- method     : up to the backend (hidden == no rendering)
81
82local nofautoattachments, lastregistered = 0, nil
83
84local function checkregistered(specification)
85    local registered = specification.registered
86    if not registered or registered == "" or registered == v_auto then
87        nofautoattachments = nofautoattachments + 1
88        lastregistered = "attachment-" .. nofautoattachments
89        specification.registered = lastregistered
90        return lastregistered
91    else
92        return registered
93    end
94end
95
96local function checkbuffer(specification)
97    local buffer = specification.buffer
98    if buffer ~= "" then
99        specification.data = buffers.getcontent(buffer) or "<no data>"
100    end
101end
102
103function attachments.register(specification) -- beware of tag/registered mixup(tag is namespace)
104    local registered = checkregistered(specification)
105    checkbuffer(specification)
106    attachments[registered] = specification
107    if trace_attachments then
108        report_attachments("registering %a",registered)
109    end
110    return specification
111end
112
113function attachments.insert(specification)
114    local registered = checkregistered(specification)
115    local r = attachments[registered]
116    if r then
117        if trace_attachments then
118            report_attachments("including registered %a",registered)
119        end
120        for k, v in next, r do
121            local s = specification[k]
122            if s == "" then
123                specification[k] = v
124            end
125        end
126    elseif trace_attachments then
127        report_attachments("including unregistered %a",registered)
128    end
129    checkbuffer(specification)
130    return nodeinjections.attachfile(specification)
131end
132
133implement {
134    name      = "registerattachment",
135    actions   = attachments.register,
136    arguments = {
137        {
138            { "tag" },
139            { "registered" },
140            { "title" },
141            { "subtitle" },
142            { "author" },
143            { "file" },
144            { "name" },
145            { "buffer" },
146            { "mimetype" },
147        }
148    }
149}
150
151implement {
152    name      = "insertattachment",
153    actions   = function(specification)
154                    texsetbox("b_scrn_attachment_link",(attachments.insert(specification)))
155                end,
156    arguments = {
157        {
158            { "tag" },
159            { "registered" },
160            { "method" },
161            { "width", "dimen" },
162            { "height", "dimen" },
163            { "depth", "dimen" },
164            { "colormodel", "integer" },
165            { "colorvalue", "integer" },
166            { "color" },
167            { "transparencyvalue", "integer" },
168            { "symbol" },
169            { "layer" },
170            { "title" },
171            { "subtitle" },
172            { "author" },
173            { "file" },
174            { "name" },
175            { "buffer" },
176            { "mimetype" },
177        }
178    }
179}
180
181-- Comment
182
183function comments.insert(specification)
184    local buffer = specification.buffer
185    if buffer ~= "" then
186        specification.data = buffers.getcontent(buffer) or ""
187    end
188    return nodeinjections.comment(specification)
189end
190
191implement {
192    name      = "insertcomment",
193    actions   = function(specification)
194                    texsetbox("b_scrn_comment_link",(comments.insert(specification)))
195                end,
196    arguments = {
197        {
198            { "tag" },
199            { "title" },
200            { "subtitle" },
201            { "author" },
202            { "width", "dimen" },
203            { "height", "dimen" },
204            { "depth", "dimen" },
205            { "nx" },
206            { "ny" },
207            { "colormodel", "integer" },
208            { "colorvalue", "integer" },
209            { "transparencyvalue", "integer" },
210            { "option" },
211            { "symbol" },
212            { "buffer" },
213            { "layer" },
214            { "space" },
215        }
216    }
217}
218
219-- Soundclips
220
221function soundclips.register(specification)
222    local tag = specification.tag
223    if tag and tag ~= "" then
224        local filename = specification.file
225        if not filename or filename == "" then
226            filename = tag
227            specification.file = filename
228        end
229        soundclips[tag] = specification
230        return specification
231    end
232end
233
234function soundclips.insert(specification)
235    local tag = specification.tag
236    if tag and tag ~= "" then
237        local sc = soundclips[tag]
238        if not sc then
239            -- todo: message
240            sc = soundclips.register { tag = tag }
241        end
242        nodeinjections.insertsound(sc)
243    end
244end
245
246implement {
247    name      = "registersoundclip",
248    actions   = soundclips.register,
249    arguments = {
250        {
251            { "tag" },
252            { "file" }
253        }
254    }
255}
256
257implement {
258    name      = "insertsoundclip",
259    actions   = soundclips.insert,
260    arguments = {
261        {
262            { "tag" },
263            { "repeat" }
264        }
265    }
266}
267
268-- Renderings
269
270function renderings.register(specification)
271    if specification.label then
272        renderings[specification.label] = specification
273        return specification
274    end
275end
276
277function renderings.rendering(label)
278    local rn = renderings[label]
279    if not rn then
280        -- todo: message
281        return renderings.register { label = label }
282    else
283        return rn
284    end
285end
286
287function renderings.var(label,key)
288    local rn = renderings[label]
289    return rn and rn[key] or ""
290end
291
292implement {
293    name      = "renderingvar",
294    actions   = { renderings.var, context },
295    arguments = "2 strings",
296}
297
298implement {
299    name      = "registerrendering",
300    actions   = renderings.register,
301    arguments = {
302        {
303            { "label" },
304            { "mime" },
305            { "filename" },
306            { "option" },
307        }
308    }
309}
310
311-- Rendering:
312
313implement {
314    name      = "insertrenderingwindow",
315    actions   = function(specification)
316                    codeinjections.insertrenderingwindow(specification)
317                end,
318    arguments = {
319        {
320            { "label" },
321            { "width", "dimen" },
322            { "height", "dimen"  },
323            { "option" },
324            { "page", "integer" },
325            { "openpage" },
326            { "closepage" },
327        }
328    }
329}
330
331-- Linkedlists (only a context interface)
332
333implement {
334    name      = "definelinkedlist",
335    arguments = "string",
336    actions   = function(tag)
337                    -- no need
338                end
339}
340
341implement {
342    name      = "enhancelinkedlist",
343    arguments = { "string", "integer" },
344    actions   = function(tag,n)
345                    local ll = jobpasses.gettobesaved(tag)
346                    if ll then
347                        ll[n] = texgetcount("realpageno")
348                    end
349                end
350}
351
352implement {
353    name      = "addlinklistelement",
354    arguments = "string",
355    actions   = function(tag)
356                    local tobesaved   = jobpasses.gettobesaved(tag)
357                    local collected   = jobpasses.getcollected(tag) or { }
358                    local currentlink = #tobesaved + 1
359                    local noflinks    = #collected
360                    tobesaved[currentlink] = 0
361                    local f = collected[1] or 0
362                    local l = collected[noflinks] or 0
363                    local p = collected[currentlink-1] or f
364                    local n = collected[currentlink+1] or l
365                    context.setlinkedlistproperties(currentlink,noflinks,f,p,n,l)
366                 -- context.ctxlatelua(function() commands.enhancelinkedlist(tag,currentlink) end)
367                end
368}
369