typo-shp.lmt /size: 8974 b    last modification: 2021-10-28 13:51
1if not modules then modules = { } end modules ['meta-imp-txt'] = {
2    version   = 1.001,
3    comment   = "companion to meta-imp-txt.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
9local setmetatableindex = table.setmetatableindex
10local settings_to_array = utilities.parsers.settings_to_array
11
12local texget       = tex.get
13local texset       = tex.set
14local texgetcount  = tex.getcount
15local texgetglue   = tex.getglue
16
17local expandmacro  = token.expandmacro or token.expand_macro -- todo
18
19local implement    = interfaces.implement
20
21local scan         = mp.scan
22local scannumeric  = scan.numeric
23local scaninteger  = scan.integer
24local scanboolean  = scan.boolean
25local scanstring   = scan.string
26
27local bpfactor     = number.dimenfactors.bp
28
29local context      = context
30
31local parshapes    = { }
32local properties   = { }
33
34metapost.registerscript("setparshapeproperty", function()
35    local k = scanstring()
36    if k == "line" then
37        local entry  = properties.shape[scannumeric()]
38        local indent = scannumeric() / bpfactor
39        local width  = scannumeric() / bpfactor
40        entry[1] = indent
41        entry[2] = width
42    elseif k == "lines" then
43        properties.lines = scaninteger()
44        properties.shape = setmetatableindex(function(t,k)
45            local v = { 0, properties.width or 0 }
46            t[k] = v
47            return v
48        end)
49    elseif k == "first" then
50        properties[k] = scanboolean()
51    elseif k == "inspect" then
52        inspect(properties)
53    else
54        properties[k] = scannumeric() / bpfactor
55    end
56end)
57
58implement {
59    name      = "setparagraphmetashape",
60    public    = true,
61    protected = true,
62    arguments = { "optional", "optional" },      -- array
63    actions   = function(list,options)
64        if list and list ~= "" then
65            list    = settings_to_array(list)    -- array
66            options = settings_to_array(options) -- array
67            if #list > 0 then
68                parshapes  = { }
69                properties = { }
70                for i=1,#list do
71                    properties = { }
72                    parshapes[i] = properties
73                    expandmacro("spac_shapes_calculate","{"..list[i].."}")
74                end
75                local t, n = { }, 0
76                for i=1,#parshapes do
77                    local p = parshapes[i]
78                    local s = p.shape
79                    if s then
80                        for i=1,(p.lines or #s) do
81                            n = n + 1
82                            t[n] = s[i]
83                        end
84                    end
85                end
86                if n > 0 then
87                    for i=1,#options do
88                        t[options[i]] = true
89                    end
90                    texset("parshape",t)
91                end
92            end
93        end
94    end
95}
96
97-- implement {
98--     name      = "resetparagraphmetashape",
99--     public    = true,
100--     protected = true,
101--     actions   = function(list)
102--         parshapes  = { }
103--         properties = { }
104--     end
105-- }
106
107implement {
108    name      = "getshapeparameter",
109    public    = true,
110    arguments = "string",
111    actions   = function(name)
112        local index = texgetcount("shapetextindex")
113        local value = parshapes[index][name]
114        if type(value) == "boolean" then
115            value = value and 1 or 0
116        end
117        context(value or 0) -- so the first check, for "lines" is always ok
118    end
119}
120
121-- Another experiment: continuing parshapes with alternative definitions:
122--
123-- left d | right d | left d right d | both d | left d hsize d |
124-- copy n | reset | repeat | done
125
126do
127
128    local scanners     = tokens.scanners
129    local scanword     = scanners.word
130    local scandimen    = scanners.dimen
131    local scanstring   = scanners.string
132    local scancardinal = scanners.cardinal
133
134    implement {
135        name      = "setparagraphshape",
136        protected = true,
137        actions   = function()
138            local t = { }
139            local n = 0
140            local h = texget("hsize")
141            local a = 0
142            while true do
143                local key = scanword()
144              ::AGAIN::
145                if key == "left" then
146                    local l = scandimen()
147                    key = scanword()
148                    if key == "right" then
149                        n = n + 1 ; t[n] = { l, a + h - l - scandimen() }
150                    elseif key == "hsize" then
151                        n = n + 1 ; t[n] = { l, a + scandimen() }
152                    else
153                        n = n + 1 ; t[n] = { l, a + h }
154                        goto AGAIN
155                    end
156                elseif key == "right" then
157                    n = n + 1 ; t[n] = { 0, a + h - scandimen() }
158                elseif key == "both" then
159                    local b = scandimen()
160                    n = n + 1 ; t[n] = { b, a + h - b - b }
161                elseif key == "copy" then
162                    local c = scancardinal()
163                    for i=1,c do
164                        local m = n + 1
165                        t[m] = t[n]
166                        n = m
167                    end
168                elseif key == "done" then
169                    -- in case the user ended with "done"
170                    scanword()
171                    break
172                elseif key == "metapost" then
173                    local list = settings_to_array(scanstring())    -- array
174                    properties = { }
175                    parshapes  = { }
176                    for i=1,#list do
177                        properties = { }
178                        parshapes[i] = properties
179                        expandmacro("spac_shapes_calculate","{"..list[i].."}")
180                    end
181                    for i=1,#parshapes do
182                        local p = parshapes[i]
183                        local s = p.shape
184                        if s then
185                            for i=1,(p.lines or #s) do
186                                local si = s[i]
187                                n = n + 1 ; t[n] = { si[1], a + si[2] }
188                            end
189                        end
190                    end
191                elseif key == "repeat" then
192                    t["repeat"] = true
193                elseif key == "delete" then
194                    local c = scancardinal()
195                    for i=1,c do
196                        if n > 0 then
197                            t[n] = nil
198                            n = n - 1
199                        else
200                            break
201                        end
202                    end
203                elseif key == "reset" then
204                    n = n + 1 ; t[n] = { 0, a + h }
205                    break
206                elseif key == "absolute" then
207                    local s = scanword()
208                    local l = texgetglue("leftskip")
209                    local r = texgetglue("rightskip")
210                    if s == "left" then
211                        a = l
212                    elseif s == "right" then
213                        a = r
214                    elseif s == "both" then
215                        a = l + r
216                    else
217                        a = l + r
218                        goto AGAIN
219                    end
220                elseif key == "inspect" then
221                    inspect(t)
222                else
223                    logs.report("system","bad key %a in paragraphshape",key)
224                    break
225                end
226            end
227            texset("parshape",t)
228        end,
229    }
230
231    local NC = context.NC
232    local NR = context.NR
233    local VL = context.VL
234
235    implement {
236        name      = "showparagraphshape",
237        protected = true,
238        public    = true,
239        actions   = function()
240            local p = texget("parshape")
241            if p then
242                -- only english interface (for now)
243                context.inleftmargin(
244                    {
245                        align   = "flushright",
246                        strut   = "no",
247                        width   = "0pt",
248                     -- voffset = "-\\lineheight"
249                    }, function()
250                        context.starttabulate {
251                            before = "",
252                            after  = "",
253                            unit   = "2pt",
254                            rulethickness = ".1pt",
255                            format = "|rb{\\smallinfofont}|lb{\\smallinfofont}|"
256                        }
257                            for i=1,#p do
258                                NC() context("%P",p[i][1])
259                                VL() context("%P",p[i][2])
260                                NC() NR()
261                            end
262                        context.stoptabulate()
263                    end
264                )
265            end
266        end
267    }
268
269end
270