-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathluauline.lua
175 lines (162 loc) · 5.89 KB
/
luauline.lua
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
local HLIST = node.id("hlist")
local VLIST = node.id("vlist")
local RULE = node.id("rule")
local GLUE = node.id("glue")
local GLUESPEC = node.id("glue_spec")
local KERN = node.id("kern")
local WHAT = node.id("whatsit")
local USER = node.subtype("user_defined")
local MARGIN_KERN = node.id('margin_kern')
function string.starts(String,Start)
return string.sub(String,1,string.len(Start)) == Start
end
local check_whatsit_user_string = function(item)
if item.id == WHAT and item.subtype == USER and item.type == 115 then
return true
end
return false
end
create_user_node = function(data)
local temp_user_node = node.new(WHAT, USER)
temp_user_node.type = 115
temp_user_node.value = data
node.write(temp_user_node)
end
create_user_rule_node = function(depth, height)
local temp_user_node = node.new(WHAT, USER)
local temp_rule_node = node.new(RULE)
temp_rule_node.height = -tex.sp(depth)
temp_rule_node.depth = tex.sp(depth) + tex.sp(height)
temp_user_node.type = 110
temp_user_node.value = node.copy(temp_rule_node)
node.write(temp_user_node)
end
create_user_leaders_node = function()
local temp_user_node = node.new(WHAT, USER)
local item_leader = node.new(GLUE)
if not item_leader.width then
local item_leader_spec = node.new(GLUESPEC)
item_leader_spec.width, item_leader_spec.stretch, item_leader_spec.shrink = 0, 0, 0
item_leader.spec = item_leader_spec
else
item_leader.width, item_leader.stretch, item_leader.shrink = 0, 0, 0
end
item_leader.subtype = 101
item_leader.leader = node.copy(tex.getbox("lua@underline@box"))
temp_user_node.type = 110
temp_user_node.value = node.copy(item_leader)
node.write(temp_user_node)
end
create_user_hlist_node = function()
local temp_user_node =node.new(WHAT, USER)
temp_user_node.type = 110
temp_user_node.value = node.copy(tex.getbox("lua@underline@box"))
node.write(temp_user_node)
end
underline_numbers = { }
local get_instances
get_instances = function (head, prefix, separator)
if next(underline_numbers) then
local current_instances = { }
for line in node.traverse(head) do
local item = line.head
while item do
if check_whatsit_user_string(item) and string.starts(item.value, prefix .. separator) then
local current_instance = { }
table.insert(current_instance, string.sub(item.value,string.len(prefix)+string.len(separator)+1))
item = item.next
table.insert(current_instance, item.value)
table.insert(current_instances, current_instance)
elseif item.id == HLIST or item.id == VLIST then
for _,entry in ipairs(get_instances(item, prefix, separator)) do
table.insert(current_instances, entry)
end
end
item = item.next
end
end
return current_instances
end
return { }
end
local good_item = function(item)
if item.id == MARGIN_KERN or (item.id == GLUE and (item.subtype == 8 or item.subtype == 9 or item.subtype == 15)) then
return false
else
return true
end
end
local insert_single_underline = function (head, ratio, sign, order, item, end_node, action)
local temp_width = node.dimensions(ratio, sign, order, item, end_node.next)
local new_item = nil
if action.id == RULE then
new_item = node.new(RULE)
new_item.depth = action.depth
new_item.height = action.height
new_item.width = temp_width
elseif action.id == HLIST then
new_item = node.new(HLIST)
new_item = node.copy(action)
new_item.width = temp_width/2
temp_width = temp_width/2
elseif action.id == GLUE then
new_item = node.new(GLUE)
if not item.width then
new_item_spec = node.new(GLUESPEC)
new_item_spec.width, new_item_spec.stretch, new_item_spec.shrink = temp_width, 0, 0
new_item.spec = new_item_spec
else
new_item.width, new_item.stretch, new_item.shrink = temp_width, 0, 0
end
new_item.subtype = 101
new_item.leader = node.copy(action.leader)
end
local item_kern = node.new(KERN, 1)
item_kern.kern = -temp_width
node.insert_after(head, end_node, item_kern)
node.insert_after(head, item_kern, new_item)
return new_item
end
local underline
underline = function (head, order, ratio, sign, index, action, cont)
local newcontinue = false
local item = head
while item do
if item.id == HLIST or item.id == VLIST then
newcontinue = underline(item.head, item.glue_order, item.glue_set, item.glue_sign, index, action, cont)
item = item.next
elseif cont or ( check_whatsit_user_string(item) and string.starts(item.value,"lua@underline@start@" .. index) ) then
if check_whatsit_user_string(item) and string.starts(item.value,"lua@underline@start@" .. index) then
node.remove(head, item)
end
cont = false
while not good_item(item) do -- strip off leading glue of types 8, 9, and 15
item = item.next
end
local end_node = item
while end_node.next and not ( check_whatsit_user_string(end_node.next) and string.starts(end_node.next.value, "lua@underline@stop@" .. index) ) and good_item(end_node.next) do
end_node = end_node.next
end
if not ( end_node.next and check_whatsit_user_string(end_node.next) and string.starts(end_node.next.value, "lua@underline@stop@" .. index) ) then
newcontinue = true
else
underline_numbers[tonumber(index)] = nil
end
new_item = insert_single_underline(head, ratio, sign, order, item, end_node, action)
item = new_item.next
else
item = item.next
end
end
return newcontinue
end
local get_lines = function (head)
local continue = false
for _,entry in ipairs(get_instances(head, "lua@underline@start", "@")) do
for line in node.traverse_id(HLIST, head) do
continue = underline(line.head, line.glue_order, line.glue_set, line.glue_sign, entry[1], entry[2], continue)
end
end
return head
end
luatexbase.add_to_callback("post_linebreak_filter", get_lines, "underline")