1if not modules then modules = { } end modules ['anch-snc'] = {
2 version = 1.001,
3 comment = "companion to anch-snc.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
10
11
12local tonumber, next, setmetatable = tonumber, next, setmetatable
13local concat, sort, remove, copy = table.concat, table.sort, table.remove, table.copy
14local match, find = string.match, string.find
15local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
16
17local P, Cc = lpeg.P, lpeg.Cc
18
19local setmetatableindex = table.setmetatableindex
20
21local factor = number.dimenfactors.bp
22local mpprint = mp.print
23local mpnumeric = mp.numeric
24local mppoints = mp.points
25local texgetdimen = tex.getdimen
26
27local p_number = lpegpatterns.cardinal/tonumber
28local p_space = lpegpatterns.whitespace^0
29local p_tag = P("syncpos:") * p_number * P(":") * p_number
30local p_option = p_number * ((P(",") * p_space * P("reset") * Cc(true)) + Cc(false))
31
32local list = { }
33local colors = setmetatableindex("table")
34
35local kinds = {
36 above = 1,
37 continue = 2,
38 nothing = 3,
39 normal = 4,
40 below = 5,
41}
42
43local allentries = setmetatableindex(function(t,category)
44 setmetatable(t,nil)
45 for tag, pos in next, job.positions.collected do
46 local c, n = lpegmatch(p_tag,tag)
47 if c then
48 local tc = t[c]
49 if tc then
50 tc[n] = pos
51 else
52 t[c] = { [n] = pos }
53 end
54 end
55 end
56 for k, list in next, t do
57 sort(list,function(a,b)
58 local ap = a.p
59 local bp = b.p
60 if ap == bp then
61 return b.y < a.y
62 else
63 return ap < bp
64 end
65 end)
66 list.start = 1
67 end
68 setmetatableindex(t,"table")
69 return t[category]
70end)
71
72local lastdone = { }
73
74function mp.sync_collect(category,realpage,useregion)
75 local all = allentries[category]
76 local m = 0
77 local n = #all
78 list = { }
79 if useregion then
80
81 local start = 1
82 local done = false
83 local last, rtop, rbot
84 for i=start,n do
85 local pos = all[i]
86 local p = pos.p
87 local r = pos.r
88 if r == useregion then
89 if not done then
90 local region = job.positions.collected[r]
91 list.region = region
92 list.page = region
93 rtop = (region.y or 0) + (region.h or 0)
94 rbot = (region.y or 0) - (region.d or 0)
95 last = { kind = "nothing", top = rtop, bottom = 0, task = 0 }
96 m = m + 1 ; list[m] = last
97 done = true
98 end
99 local top = pos.y + pos.h
100 last.bottom = top
101 local task, reset = lpegmatch(p_option,pos.e)
102 last = { kind = "normal", top = top, bottom = 0, task = task }
103 m = m + 1 ; list[m] = last
104 end
105 end
106 if done then
107 last.bottom = rbot
108 end
109 else
110 local start = all.start or 1
111 local done = false
112 local last, rtop, rbot, ptop, pbot
113 for i=start,n do
114 local pos = all[i]
115 local p = pos.p
116 if p == realpage then
117 if not done then
118 local region = job.positions.collected[pos.r]
119 local page = job.positions.collected["page:"..realpage] or region
120 list.region = region
121 list.page = page
122 rtop = (region.y or 0) + (region.h or 0)
123 rbot = (region.y or 0) - (region.d or 0)
124 ptop = (page .y or 0) + (page .h or 0)
125 pbot = (page .y or 0) - (page .d or 0)
126 last = { kind = "above", top = ptop, bottom = rtop, task = 0 }
127 m = m + 1 ; list[m] = last
128 if i > 1 then
129 local task, reset = lpegmatch(p_option,all[i-1].e)
130 last = { kind = "continue", top = rtop, bottom = 0, task = task }
131 m = m + 1 ; list[m] = last
132 else
133 last = { kind = "nothing", top = rtop, bottom = 0, task = 0 }
134 m = m + 1 ; list[m] = last
135 end
136 done = true
137 end
138 local top = pos.y + pos.h
139 last.bottom = top
140 local task, reset = lpegmatch(p_option,pos.e)
141 if reset then
142 local l = list[2]
143 l.kind = "nothing"
144 l.task = 0
145 end
146 last = { kind = "normal", top = top, bottom = 0, task = task }
147 m = m + 1 ; list[m] = last
148 elseif p > realpage then
149 all.start = i
150 break
151 end
152 end
153 if done then
154 last.bottom = rbot
155 last = { kind = "below", top = rbot, bottom = pbot, task = 0 }
156 m = m + 1 ; list[m] = last
157 lastdone[category] = {
158 { kind = "above", top = ptop, bottom = rtop, task = 0 },
159 { kind = "continue", top = rtop, bottom = rbot, task = list[#list-1].task },
160 { kind = "below", top = rbot, bottom = pbot, task = 0 },
161 region = list.region,
162 page = list.page,
163 }
164 else
165 local l = lastdone[category]
166 if l then
167 list = copy(l)
168 m = 3
169 end
170 end
171 end
172 mpnumeric(m)
173end
174
175function mp.sync_extend()
176 local n = #list
177 if n > 0 then
178 for i=1,n do
179 local l = list[i]
180 local k = l.kind
181 if k == "nothing" then
182 local ll = list[i+1]
183 if ll and ll.kind == "normal" then
184 ll.top = l.top
185 remove(list,i)
186 n = #list
187 break
188 end
189 end
190 end
191 end
192 mpnumeric(n)
193end
194
195function mp.sync_prune()
196 local n = #list
197 if n > 0 then
198 if list[1].kind == "above" then
199 remove(list,1)
200 end
201 if list[1].kind == "nothing" then
202 remove(list,1)
203 end
204 if list[#list].kind == "below" then
205 remove(list,#list)
206 end
207 n = #list
208 end
209 mpnumeric(n)
210end
211
212function mp.sync_collapse()
213 local n = #list
214 if n > 0 then
215 local m = 0
216 local p = nil
217 for i=1,n do
218 local l = list[i]
219 local t = l.task
220 if p == t then
221 list[m].bottom = l.bottom
222 else
223 m = m + 1
224 list[m] = l
225 end
226 p = t
227 end
228 for i=n,m+1,-1 do
229 list[i] = nil
230 end
231 n = m
232 end
233 mpnumeric(n)
234end
235
236function mp.sync_set_color(category,n,v)
237 colors[category][n] = v
238end
239
240function mp.sync_get_color(category,n)
241 mpprint(colors[category][n])
242end
243
244
245
246
247
248
249
250
251
252
253
254
255
256function mp.sync_get_size () mpnumeric(#list) end
257function mp.sync_get_top (n) mpnumeric(list[n].top * factor) end
258function mp.sync_get_bottom(n) mpnumeric(list[n].bottom * factor) end
259function mp.sync_get_kind (n) mpnumeric(kinds[list[n].kind]) end
260function mp.sync_get_task (n) mpnumeric(list[n].task) end
261
262function mp.sync_get_x() mpnumeric((list.page.x or 0)*factor) end
263function mp.sync_get_y() mpnumeric((list.page.y or 0)*factor) end
264function mp.sync_get_w() mpnumeric((list.page.w or 0)*factor) end
265function mp.sync_get_h() mpnumeric((list.page.h or 0)*factor) end
266function mp.sync_get_d() mpnumeric((list.page.d or 0)*factor) end
267
268
269
270
271
272
273 |