summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/typo-cln.lua
blob: a2ebe6a0a66bb85bed08f577cb3c29cc0b58dae2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
if not modules then modules = { } end modules ['typo-cln'] = {
    version   = 1.001,
    comment   = "companion to typo-cln.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

-- This quick and dirty hack took less time than listening to a CD (In
-- this case Dream Theaters' Octavium). Of course extensions will take
-- more time.

local tonumber = tonumber
local utfbyte = utf.byte

local trace_cleaners = false  trackers.register("typesetters.cleaners",         function(v) trace_cleaners = v end)
local trace_autocase = false  trackers.register("typesetters.cleaners.autocase",function(v) trace_autocase = v end)

local report_cleaners = logs.reporter("nodes","cleaners")
local report_autocase = logs.reporter("nodes","autocase")

typesetters.cleaners  = typesetters.cleaners or { }
local cleaners        = typesetters.cleaners

local variables       = interfaces.variables

local nodecodes       = nodes.nodecodes

local enableaction    = nodes.tasks.enableaction

local texsetattribute = tex.setattribute

local nuts            = nodes.nuts

local getchar         = nuts.getchar
local getattr         = nuts.getattr
local setattr         = nuts.setattr

local setchar         = nuts.setchar

local nextglyph       = nuts.traversers.glyph

local unsetvalue      = attributes.unsetvalue

local glyph_code      = nodecodes.glyph
local uccodes         = characters.uccodes

local a_cleaner       = attributes.private("cleaner")

local resetter = { -- this will become an entry in char-def
    [utfbyte(".")] = true
}

-- Contrary to the casing code we need to keep track of a state.
-- We could extend the casing code with a status tracker but on
-- the other hand we might want to apply casing afterwards. So,
-- cleaning comes first.

function cleaners.handler(head)
    local inline = false
    for n in nextglyph, head do
        local char = getchar(n)
        if resetter[char] then
            inline = false
        elseif not inline then
            local a = getattr(n,a_cleaner)
            if a == 1 then -- currently only one cleaner so no need to be fancy
                local upper = uccodes[char]
                if type(upper) == "table" then
                    -- some day, not much change that \SS ends up here
                else
                    setchar(n,upper)
                    if trace_autocase then
                        report_autocase("")
                    end
                end
            end
            inline = true
        end
    end
    return head
end

if LUATEXVERSION >= 1.080 then

    function cleaners.handler(head)
        local inline = false
        for n, font, char in nextglyph, head do
            if resetter[char] then
                inline = false
            elseif not inline then
                local a = getattr(n,a_cleaner)
                if a == 1 then -- currently only one cleaner so no need to be fancy
                    local upper = uccodes[char]
                    if type(upper) == "table" then
                        -- some day, not much change that \SS ends up here
                    else
                        setchar(n,upper)
                        if trace_autocase then
                            report_autocase("")
                        end
                    end
                end
                inline = true
            end
        end
        return head
    end

end

-- see typo-cap for a more advanced settings handler .. not needed now

local enabled = false

function cleaners.set(n)
    if n == variables.reset or not tonumber(n) or n == 0 then
        texsetattribute(a_cleaner,unsetvalue)
    else
        if not enabled then
            enableaction("processors","typesetters.cleaners.handler")
            if trace_cleaners then
                report_cleaners("enabling cleaners")
            end
            enabled = true
        end
        texsetattribute(a_cleaner,tonumber(n))
    end
end

-- interface

interfaces.implement {
    name      = "setcharactercleaning",
    actions   = cleaners.set,
    arguments = "string"
}