m-catchword.mkiv /size: 3424 b    last modification: 2021-10-28 13:51
1%D \module
2%D   [       file=m-catchword,
3%D        version=2019.08.09,
4%D          title=\CONTEXT\ Extra Modules,
5%D       subtitle=Catchwords,
6%D         author=Hans Hagen,
7%D           date=\currentdate,
8%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
9%C
10%C This module is part of the \CONTEXT\ macro||package and is
11%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
12%C details.
13
14\startluacode
15
16-- If someone realy need it there probably is no need for speed, so we do
17-- it quick and dirty.
18
19local nodecodes     = nodes.nodecodes
20local kerncodes     = nodes.kerncodes
21
22local glyph_code    = nodecodes.glyph
23local disc_code     = nodecodes.disc
24local kern_code     = nodecodes.kern
25local hlist_code    = nodecodes.hlist
26
27local fontkern_code = kerncodes.fontkern
28
29local function set_catchword(t)
30    local nextpage = tex.lists.contribute_head or tex.lists.contrib_head
31    if not nextpage then
32        return
33    end
34    local firstline = nil
35    for n in nodes.traverse_id(hlist_code,nextpage) do
36        firstline = n
37        break
38    end
39    if not firstline then
40        return
41    end
42    local list = firstline.list
43    if not list then
44        return
45    end
46    local first = nil
47    local last  = nil
48    for n, id, subtype in nodes.traverse(list) do
49        if id == glyph_code or id == disc_code or (id == kern_code and subtype == fontkern_code) then
50            if not first then
51                first = n
52            end
53            last = n
54        elseif first then
55            break
56        end
57    end
58    if not first then
59        return
60    end
61    local page = tex.getbox(t.box)
62    local head = nodes.copy_list(first,last.next)
63          head = nodes.insertbefore(head,head,nodes.pool.glue(1,1,1))
64    local line = nodes.hpack(head,page.width,"exactly")
65    if CONTEXTLMTXMODE > 0 then
66        line.yoffset = -t.voffset
67        line.xoffset = t.hoffset
68    else
69        line.shift = t.hoffset
70        line = nodes.insertbefore(line,line,nodes.pool.kern(t.voffset-line.height))
71        line = nodes.vpack(line)
72    end
73    line.height  = 0
74    line.depth   = 0
75    nodes.insertafter(page.list,nodes.tail(page.list),line)
76    logs.report("catchword","appending %a on page %i",nodes.toutf(head),tex.getcount("realpageno"))
77end
78
79interfaces.implement {
80    name      = "set_catchword",
81    actions   = set_catchword,
82    arguments = {
83        {
84            { "box",     "integer" },
85            { "hoffset", "dimension" },
86            { "voffset", "dimension" },
87        },
88    },
89}
90
91\stopluacode
92
93\unprotect
94
95\installcorenamespace {catchword}
96
97\installsimplecommandhandler \??catchword {catchword}
98
99\setupcatchword
100  [\c!state=\v!stop,
101   \c!hoffset=\zeropoint,
102   \c!voffset=\lineheight]
103
104\def\page_check_catchword_yes#1%
105  {\clf_set_catchword
106     box     #1
107     hoffset \catchwordparameter\c!hoffset
108     voffset \catchwordparameter\c!voffset
109   \relax}
110
111\let\page_check_catchword_nop\gobbleoneargument
112
113\appendtoks
114    \doifelse{\catchwordparameter\c!state}\v!start
115      {\let\page_check_catchword\page_check_catchword_yes}%
116      {\let\page_check_catchword\page_check_catchword_nop}%
117\to \everysetupcatchword
118
119\appendtoks
120    \page_check_catchword\b_page_postprocessor
121\to \t_page_postprocessors_page
122
123\protect
124
125\continueifinputfile{m-catchword.mkiv}
126
127\setupcatchword
128  [state=start,
129   hoffset=.75em,
130   voffset=1cm]
131
132\starttext
133
134    \dorecurse{100}{\input ward }
135
136\stoptext
137