summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/fontinst/base/multislot.sty
blob: fac721440591b4d22dc8b977d6452ec1267b8fc2 (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
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
% multislot.sty
% 
% Second version


\needsfontinstversion{1.900} 
% Relies heavily on _etx_pass_hook commands.


%%%%%%%%%%%%%%% RESOURCES USED %%%%%%%%%%%%%%%
% 
% The following classes of control sequences are used by the multislot 
% routines, in addition to the ones defined below and the ones fontinst 
% normally uses:
% 
%    \name-NUM
% 
% where NUM is a number consisting of one, two, or three decimal digits. 
% These are also used by \pltomtx, so they probably already exist as 
% hash table entries.



%%%%%%%%%%%%%%% SAVE CATCODES %%%%%%%%%%%%%%%
%
% Save the current values of the catcodes of space, @, NL, ~ and _.
% _ and @ are made letters, ~ is a space, and space and NL are ignored.

\edef\spacecatcode{\the\catcode`\ }
\edef\atcatcode{\the\catcode`\@}
\edef\nlcatcode{\the\catcode`\^^M}
\edef\underscorecatcode{\the\catcode`\_}
\edef\tildecatcode{\the\catcode`\~}

\catcode`\ =9
\catcode`\^^M=9
\catcode`\@=11
\catcode`\_=11
\catcode`\~=10


%%%%%%%%%%%%%%% MULTIPLE SLOT COMMANDS %%%%%%%%%%%%%%%
% 
% The user-level commands are quite simple. As usual, you can write
% 
%    \setslot{NAME}
%        <slot commands>
%    \endsetslot
% 
% to assign a glyph to a slot. The difference is that if there are 
% multiple \setslot commands for a slot, this will no longer cause 
% strange results. Instead, only the first \setslot-\endsetslot pair 
% for each slot will be used, the others are ignored.
% 
% If you instead write
% 
%    \resetslot{NAME}
%        <slot commands>
%    \endsetslot
% 
% then this will override any earlier occurences of \setslot or 
% \resetslot. Finally, there is the command
% 
%    \unsetslot{NUMBER}
% 
% which makes fontinst forget any earlier occurences of \setslot 
% or \resetslot commands for that particular slot.


% The way this works is that every \setslot or \resetslot command is 
% implicitly assigned an index, namely the number of such commands 
% perviously encountered since the start of the ETX pass. The count 
% register \slot_index is allocated to keep track of the current 
% index:

\newcount\slot_index
\def\clear_slot_index{\slot_index=\m@ne}
\add_to\pre_first_etx_pass_hook{\clear_slot_index}
\add_to\pre_second_etx_pass_hook{\clear_slot_index}
\add_to\pre_third_etx_pass_hook{\clear_slot_index}
\add_to\pre_fourth_etx_pass_hook{\clear_slot_index}

% \setslot, \setleftboundary, and \setrightboundary increments the 
% counter just before checking it.



% The point of maintaining the index is that the index of the 
% \setslot (or whatever) that actually sets a particular slot gets 
% stored in the \name-SLOT control sequence (which is \mathchardef'ed 
% to the index). After assignments are made, all a \setslot (or 
% whatever) needs to do is to check whether the stored index matches 
% the current one, and gobble itself if they don't.

% The basic check is performed by the command \later_index_check. 
% This has the syntax
% 
%   \later_index_check{SLOT}{<else-code>}
% 
% and expands to nothing if this \setslot will be active, but to 
% <else-code> if it will not.
\def\later_index_check#1{
   \x_cs\ifnum {name-#1}=\slot_index 
      \expandafter\gobble_one
   \else
      \expandafter\identity_one
   \fi
}
% However, when deciding which \setslots will be active, the condition 
% to test is slightly different: is the control sequence in question 
% already defined to be a mathchar token? If it isn't, then this will 
% be the active \setslot.
\def\setslot_index_check#1{\x_cs\setslot_index_check_i{name-#1}}
\def\temp_command#1{
   \def\setslot_index_check_ii##1#1##2\setslot_index_check_ii{##1}
   \def\setslot_index_check_i##1{
      \expandafter\setslot_index_check_ii \expandafter\ifx
            \expandafter$ \meaning##1 #1 0 \setslot_index_check_ii $
         \expandafter\identity_one
      \else
         \mathchardef##1=\slot_index
         \expandafter\gobble_one
      \fi
   }
}
\expandafter\temp_command \expandafter{ \string\mathchar " }

% The stated definition of \setslot_index_check should thus be in 
% force during the first etx pass, but after that the 
% \later_index_check definition should rule.
\add_to\post_first_etx_pass_hook{
   \let\setslot_index_check=\later_index_check
}

% The following is used to ignore a \setslot--\endsetslot or 
% \setleftboundary--\endsetleftboundary construction; the argument is 
% the command which marks the end. The reason not to use 
% \gobble_setslot is that it still executes \end_do_slot, which is 
% quite wrong for the kind of ignoring done here.
\def\ignore_to_end#1{
   \bgroup
      \let#1=\fi
      \expandafter
   \egroup
   \iffalse
}


% The \setslot, \setleftboundary, and \setrightboundary commands must 
% be equipped with checks at the start.
\def\checked_setslot{
   \advance \slot_index \@ne
   \setslot_index_check{\the\slot_number}{
      \advance \slot_number \@ne
      \ignore_to_end\endsetslot
   }
   \unchecked_setslot
}

\def\checked_setleftboundary{
   \advance \slot_index \@ne
   \setslot_index_check{leftboundary}{\ignore_to_end\endsetleftboundary}
   \unchecked_setleftboundary
}

\def\checked_setrightboundary#1{
   \advance \slot_index \@ne
   \setslot_index_check{\the\slot_number}{
      \advance \slot_number \@ne
      \gobble_two
   }
   \unchecked_setrightboundary{#1}
}
\add_to\pre_first_etx_pass_hook{
   \let\unchecked_setslot=\setslot
   \let\setslot=\checked_setslot
   \let\unchecked_setleftboundary=\setleftboundary
   \let\setleftboundary=\checked_setleftboundary
   \let\unchecked_setrightboundary=\setrightboundary
   \let\setrightboundary=\checked_setrightboundary
}
% But that's it, as far as the \set... commands are concerned.


% What about \unsetslot? In principle, it _should_ just be a matter of
\def\unsetslot#1{
   \eval_expr{#1}
   \x_cs\let{name-\the\result}\undefined_command
}
\add_to\post_first_etx_pass_hook{\let\unsetslot=\gobble_one}
% given which \resetslot is simply
\def\resetslot{\unsetslot\slot_number \setslot}
% and this sort-of works, but not quite.
% 
% The problem is that the ordinary slot assignment table, which is 
% used for ligature and kerning instructions, is not updated by 
% \unsetslot. Hence ligatures and kerns will be generated as if all 
% glyphs that have been set for a slot are present there; after
% 
%   \nextslot{108}
%   \setslot{l} \endsetslot
%   
%   \nextslot{108}
%   \resetslot{lambda} \endsetslot
% 
% the effect will be as if one had given the command 
% 
%   \setleftkerning{lambda}{l}{1000}
% 
% and moreover the same happens for ligatures, so an f + l -> fl 
% ligature will also work as an f + lambda -> fl ligature.
% 
% This is of course a BUG, and there doesn't seem to be any way 
% around it, short of adding another pass of reading ETX files. Doing 
% so would probably not be worth the effort, since the usefulness of 
% a \resetslot command is not clear; unlike \resetglyph, it cannot be 
% used to amend an existing \set..., but only to override it.



%%%%%%%%%%%%%%% RESTORE CATCODES %%%%%%%%%%%%%%%
%
% Restore the catcodes that were changed.

\catcode`\@=\atcatcode
\catcode`\^^M=\nlcatcode
\catcode`\ =\spacecatcode
\catcode`\~=\tildecatcode
\catcode`\_=\underscorecatcode

%%%%%%%%%%%%%%% THE END %%%%%%%%%%%%%%%

\endinput