scrn-wid.lmt /size: 9970 b    last modification: 2023-12-21 09:44
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 renderings         = allocate()
37local linkedlists        = allocate()
38
39interactions.attachments = attachments
40interactions.renderings  = renderings
41interactions.linkedlists = linkedlists
42
43local texsetbox          = tex.setbox
44
45local texgetcount        = tex.getcount
46
47local codeinjections     = backends.codeinjections
48local nodeinjections     = backends.nodeinjections
49
50local variables          = interfaces.variables
51local v_auto             = variables.auto
52
53local trace_attachments = false  trackers.register("widgets.attachments", function(v) trace_attachments = v end)
54
55local report_attachments = logs.reporter("widgets","attachments")
56
57-- Symbols
58
59implement {
60    name      = "presetsymbollist",
61    arguments = "string",
62    actions   = function(list)
63        codeinjections.presetsymbollist(list)
64    end
65}
66
67-- Attachments
68--
69-- registered : unique id
70-- tag        : used at the tex end
71-- file       : name that the file has on the filesystem
72-- name       : name that the file will get in the output
73-- title      : up to the backend
74-- subtitle   : up to the backend
75-- author     : up to the backend
76-- method     : up to the backend (hidden == no rendering)
77
78local nofautoattachments, lastregistered = 0, nil
79
80local function checkregistered(specification)
81    local registered = specification.registered
82    if not registered or registered == "" or registered == v_auto then
83        nofautoattachments = nofautoattachments + 1
84        lastregistered = "attachment-" .. nofautoattachments
85        specification.registered = lastregistered
86        return lastregistered
87    else
88        return registered
89    end
90end
91
92local function checkbuffer(specification)
93    local buffer = specification.buffer
94    if buffer ~= "" then
95        specification.data = buffers.getcontent(buffer) or "<no data>"
96    end
97end
98
99function attachments.register(specification) -- beware of tag/registered mixup(tag is namespace)
100    local registered = checkregistered(specification)
101    checkbuffer(specification)
102    attachments[registered] = specification
103    if trace_attachments then
104        report_attachments("registering %a",registered)
105    end
106    return specification
107end
108
109function attachments.insert(specification)
110    local registered = checkregistered(specification)
111    local r = attachments[registered]
112    if r then
113        if trace_attachments then
114            report_attachments("including registered %a",registered)
115        end
116        for k, v in next, r do
117            local s = specification[k]
118            if s == "" then
119                specification[k] = v
120            end
121        end
122    elseif trace_attachments then
123        report_attachments("including unregistered %a",registered)
124    end
125    checkbuffer(specification)
126    return nodeinjections.attachfile(specification)
127end
128
129implement {
130    name      = "registerattachment",
131    actions   = attachments.register,
132    arguments = {
133        {
134            { "tag" },
135            { "registered" },
136            { "title" },
137            { "subtitle" },
138            { "author" },
139            { "file" },
140            { "name" },
141            { "buffer" },
142            { "mimetype" },
143        }
144    }
145}
146
147implement {
148    name      = "insertattachment",
149    actions   = function(specification)
150                    texsetbox("b_scrn_attachment_link",(attachments.insert(specification)))
151                end,
152    arguments = {
153        {
154            { "tag" },
155            { "registered" },
156            { "method" },
157            { "width", "dimen" },
158            { "height", "dimen" },
159            { "depth", "dimen" },
160            { "colormodel", "integer" },
161            { "colorvalue", "integer" },
162            { "color" },
163            { "transparencyvalue", "integer" },
164            { "symbol" },
165            { "layer" },
166            { "title" },
167            { "subtitle" },
168            { "author" },
169            { "file" },
170            { "name" },
171            { "buffer" },
172            { "mimetype" },
173        }
174    }
175}
176
177-- Comment
178
179function comments.insert(specification)
180    local buffer = specification.buffer
181    if buffer ~= "" then
182        specification.data = buffers.getcontent(buffer) or ""
183    end
184    return nodeinjections.comment(specification)
185end
186
187implement {
188    name      = "insertcomment",
189    actions   = function(specification)
190                    texsetbox("b_scrn_comment_link",(comments.insert(specification)))
191                end,
192    arguments = {
193        {
194            { "tag" },
195            { "title" },
196            { "subtitle" },
197            { "author" },
198            { "width", "dimen" },
199            { "height", "dimen" },
200            { "depth", "dimen" },
201            { "nx" },
202            { "ny" },
203            { "colormodel", "integer" },
204            { "colorvalue", "integer" },
205            { "transparencyvalue", "integer" },
206            { "option" },
207            { "symbol" },
208            { "buffer" },
209            { "layer" },
210            { "space" },
211        }
212    }
213}
214
215-- Renderings
216
217function renderings.register(specification)
218    if specification.label then
219        renderings[specification.label] = specification
220        return specification
221    end
222end
223
224function renderings.rendering(label)
225    local rn = renderings[label]
226    if not rn then
227        -- todo: message
228        return renderings.register { label = label }
229    else
230        return rn
231    end
232end
233
234function renderings.var(label,key)
235    local rn = renderings[label]
236    return rn and rn[key] or ""
237end
238
239implement {
240    name      = "renderingvar",
241    actions   = { renderings.var, context },
242    arguments = "2 strings",
243}
244
245implement {
246    name      = "registerrendering",
247    actions   = renderings.register,
248    arguments = {
249        {
250            { "label" },
251            { "mime" },
252            { "filename" },
253            { "option" },
254        }
255    }
256}
257
258-- Rendering:
259
260implement {
261    name      = "insertrenderingwindow",
262    actions   = function(specification)
263                    codeinjections.insertrenderingwindow(specification)
264                end,
265    arguments = {
266        {
267            { "label" },
268            { "width", "dimen" },
269            { "height", "dimen"  },
270            { "option" },
271            { "page", "integer" },
272            { "openpage" },
273            { "closepage" },
274        }
275    }
276}
277
278-- Linkedlists (only a context interface) .. untested, just adapted from old code.
279
280local collected = allocate()
281local tobesaved = allocate()
282
283local linkedlists = {
284    collected = collected,
285    tobesaved = tobesaved,
286}
287
288job.linkedlists = linkedlists
289
290local function initializer()
291    collected = linkedlists.collected
292    tobesaved = linkedlists.tobesaved
293end
294
295job.register("job.linkedlists.collected", tobesaved, initializer, nil)
296
297implement {
298    name      = "definelinkedlist",
299    arguments = "string",
300    actions   = function(tag)
301                    -- no need
302                end
303}
304
305implement {
306    name      = "enhancelinkedlist",
307    arguments = { "string", "integer" },
308    actions   = function(tag,n)
309                    local linkedlist = tobesaved[tag]
310                    if not linkedlist then
311                        linkedlist     = { }
312                        tobesaved[tag] = linkedlist
313                    end
314                    linkedlist[n] = texgetcount("realpageno")
315                end
316}
317
318implement {
319    name      = "addlinklistelement",
320    arguments = "string",
321    actions   = function(tag)
322                    local tobesaved   = tobesaved[tag] or { }
323                    local collected   = collected[tag] or { }
324                    local currentlink = #tobesaved + 1
325                    local noflinks    = #collected
326                    --
327                    tobesaved[currentlink] = 0 -- needs checking
328                    --
329                    local f = collected[1] or 0
330                    local l = collected[noflinks] or 0
331                    local p = collected[currentlink-1] or f
332                    local n = collected[currentlink+1] or l
333                    --
334                    context.setlinkedlistproperties(currentlink,noflinks,f,p,n,l)
335                 -- context.ctxlatelua(function() commands.enhancelinkedlist(tag,currentlink) end)
336                end
337}
338