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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
|
% Copyright 2000 Frank Mittelbach <frank.mittelbach@latex-project.org>.
% License: LPPL, version 1.3a or newer, according to
% http://www.latex-project.org/lppl.txt.
%
% This work has the LPPL maintenance status `maintained'.
%
% The Current Maintainer of this work is Werner Lemberg <wl@gnu.org>.
%
%
% This is the file dblaccnt.tex which implements support for multiple
% accents.
%
%
% The code below handles only the case of
%
% \acc1 \acc2 ... glyph
%
% with or without nesting braces.
%
% \acc1 {\acc2 a}
%
% etc. will be handled correctly by removing the brace group during
% the scanning process. This means in particular that conceptually
% any accent command can only handle single token arguments!
%
% It should also work for combinations generated from inputenc, i.e.,
% are presented as 8bit tokens or, after passing through something like
% an .aux file, as \IeC{\acc1} \IeC{\acc2} ...
%
% If you use OT1 encoding you have to explicitly reload it (with
% \usepackage[OT1]{fontenc}).
%
%
% History
%
% 1.0 2000/01/27
%
% Initial release.
%
% 1.1 2005/04/21
%
% Make it work with LaTeX release 2003/12/01.
% Add copyright message and history.
%
\ProvidesPackage{dblaccnt}[2005/04/21 v1.1 double accent support]
\endlinechar \m@ne
% We must redefine two internal LaTeX commands to provide hooks for
% assembling accents.
% Here we test whether #1 (the command to be executed) is \chardef or
% #3 (the encoding) is `?'. If both are false, \assemble@accent@cmds
% will be used.
%
% The first case catches \DeclareTextSymbol, the second catches
% \ProvideTextCommandDefault. Both checks are ugly hacks which hopefully
% disappear in the near future.
%
\def\@dec@text@cmd#1#2#3{
\ifx#1\chardef
\expandafter\def\expandafter#2\expandafter{
\csname#3-cmd\expandafter\endcsname
\expandafter#2
\csname#3\string#2\endcsname
}
\else
\ifx#1\chardef@text@cmd
\expandafter\def\expandafter#2\expandafter{
\csname#3-cmd\expandafter\endcsname
\expandafter#2
\csname#3\string#2\endcsname
}
\else
\if#3?
\expandafter\def\expandafter#2\expandafter{
\csname#3-cmd\expandafter\endcsname
\expandafter#2
\csname#3\string#2\endcsname
}
\else
\expandafter\def\expandafter#2\expandafter{
% start looking for acc tokens
\expandafter\assemble@accent@cmds
\csname#3-cmd\expandafter\endcsname
\expandafter#2
\csname#3\string#2\endcsname
}
\fi
\fi
\fi
\let\@ifdefinable\@rc@ifdefinable
\expandafter#1\csname#3\string#2\endcsname
}
% The redefined \@tabacckludge macro below assures that the top-level
% definition of the accents (which contains \assemble@accent@cmds)
% will be called.
%
\def\@make@tabacc#1#2{
\expandafter\def\csname @tabacc\string#1\endcsname{#2}
}
\@make@tabacc{'}{\@acci}
\@make@tabacc{`}{\@accii}
\@make@tabacc{=}{\@acciii}
% Here the redefinition of second internal LaTeX macro.
%
\def\@tabacckludge#1{
\csname @tabacc\string#1\endcsname
}
% We only look ahead for further accents if we are to typeset.
%
\def\assemble@accent@cmds{
\ifx\protect\@typeset@protect
\expandafter\assemble@tokensinit
\fi
}
% The init is special as we have to parse over some of the expansion
% of the encoding specific command; for example, \^ might expand to
%
% \assemble@accent@cmds \OT1-cmd \^ \OT1\^
% ^^^^^^ one token
%
% We start \assemble@tokens with the number of hits so far (\@empty),
% zero the actual code for the current, e.g., \OT1\^ in the above
% example (resp. the corresponding macro in the current font
% encoding), and as a third argument we will pick up the next token
% or group in the input stream for testing.
%
\def\assemble@tokensinit#1#2#3{
% the usual test for availability in the current encoding
% similar to the test in \@changed@cmd
\@inmathwarn#2
\expandafter\ifx\csname\cf@encoding\string#2\endcsname\relax
\expandafter\ifx\csname ?\string#2\endcsname\relax
\expandafter\def\csname ?\string#2\endcsname{
\TextSymbolUnavailable#2
}
\fi
\global\expandafter\let
\csname\cf@encoding \string#2\expandafter\endcsname
\csname ?\string#2\endcsname
\fi
% here we substitute the current encoding
\expandafter\assemble@tokens@\expandafter\@empty
\csname\cf@encoding\string#2\endcsname
}
% The next commands should be considered only as a proof of concept
% -- they can most certainly be streamlined. Here is roughly what
% they do:
%
% \assemble@tokens: If the picked up token is \IeC then get rid of it
% and parse the next token (or group) which is expected to be the
% argument of \IeC. This is done by restarting the whole process.
% Otherwise we have to figure out if the current token (#3) is an
% 8-bit from inputenc, i.e., expanding to \IeC{...}. This is
% handled by calling \assemble@tokensz passing an expansion of #3
% as well as #3 (or more exactly, its first token since the braces
% get removed in this process) itself.
%
% \assemble@tokensz: Test if the expansion start with \IeC in which
% case it is assumed that it comes from an inputenc 8bit; the next
% token will be considered as its argument and used for further
% processing in \assemble@tokensx. Otherwise the unexpanded #3
% from above is used.
%
% \assemble@tokensx: If this cmd is called its third argument should
% contain a normalized token from the input stream, i.e.
%
% {..} -> ..
% \IeC{..} -> ..
% ^^xx (expanding to) \IeC{..} -> ..
%
% Now all :-) that remains is testing whether the expansion of this
% token starts with \assemble@accent@cmds, since in this case we have
% found another accent cmd.
%
% #1 is the number of hits, #2 is the real definition in that
% encoding, and #3 is the next token (or group).
%
% The macros \assemble@tokens@ and \assemble@tokens@@ are
% intermediate steps to test whether #3 is empty; if yes, we simply
% expand #2.
%
\def\assemble@tokens@#1#2#3{
\assemble@tokens@@{#1}{#2}{#3}{#3\@empty}
}
\def\assemble@tokens@@#1#2#3#4{
\ifx#4\@empty
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{#2{}}
{\assemble@tokens{#1}{#2}{#3}}
}
\def\assemble@tokens#1#2#3{
\ifx\IeC#3
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
% try again but pick up argument of \IeC
{\assemble@tokens@{#1}{#2}}
% this will get rid of a group argument -- nasty :-)
{\expandafter\assemble@tokensz#3\relax\assemble@tokensz{#1}{#2}#3}
}
\def\assemble@tokensz#1#2\assemble@tokensz#3#4#5{
\ifx#1\IeC
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\assemble@tokensx{#3}{#4}#2}
{\assemble@tokensx{#3}{#4}#5}
}
% \assemble@tokensx: This passes an expanded and unexpanded version
% of #3 to \ifassemble@tokens to do the actual processing.
%
% \ifassemble@tokens: If we have found another accent command then
% keep its name and record that we had another hit and restart the
% scanning via \assemble@tokens, i.e., we append an `x' to the
% ``hit'' argument that we carry around for no good reason, and we
% append the official name of the accent command (which was picked
% up as part of the expansion of the input token) to the argument,
% storing the list of accents found so far. Note that we do use
% the official name, e.g. `\"', not `\OT1\"' -- the latter is only
% used for the very first accent!
%
% If it turns out that we don't have an accent command here it is
% time to stop the scanning and do some processing. Now finally the
% ``hit'' argument and the list of collected accents comes into play:
% We construct a command which name consists of the string
% ``handle@accent'', followed by a number of `x's each for each hit
% earlier on. Thus in a situation like \"\^a we would execute
% \handle@accentx and in case of \"a \handle@accent. This command
% gets as its arguments the collected accents followed by the token
% which stopped the scanning proccess, e.g.
%
% \handle@accentx \OT1\" \^ {a}
%
% and its purpose is to determine how to produce a glyph from it
% (e.g. as a composite or as a part composite or ...)
%
\def\assemble@tokensx#1#2#3{
\expandafter
\ifassemble@tokens#3\@empty\@empty\@empty\ifassemble@tokens{#1}{#2}{#3}}
\def\ifassemble@tokens#1#2#3#4\ifassemble@tokens#5#6#7{
% next token was defined via \DeclareText...
\ifx#1\assemble@accent@cmds
% thus #3 is its official name
\expandafter\assemble@tokens@
\else
% execute what has been assembled and exit
\csname handle@accent#5\endcsname#6{#7}
\expandafter\@gobbletwo
\fi
% first two args to \assemble@tokens on next pass
{#5x}{#6#3}
}
% Depending on the number of accents found, \handle@accent[x[x]] will
% be called.
% ONLY ONE: We check whether \#1-#2 is a known command (a composite)
% and execute it, otherwise try to execute #1{#2} as an accent
% command.
%
\def\handle@accent#1#2{
\expandafter\ifx\csname\string#1-\string#2\endcsname\relax
#1{#2}
\else
\csname\string#1-\string#2\endcsname
\fi
}
% TWO IN A ROW: We check for \#1-#2-#3. If undefined, we apply #1 to
% whatever is the result of #2{#3}. One could think of a more
% complex algorithm here, e.g., if #1-#2 is known as a composite
% modifier (whatever that is) apply that before trying the above but
% this is probably not necessary.
%
\def\handle@accentx#1#2#3{
\expandafter\ifx\csname\string#1-\string#2-\string#3\endcsname\relax
#1{#2{#3}}
\else
\csname\string#1-\string#2-\string#3\endcsname
\fi
}
% MORE THAN TWO: (Not handled so far.) If there are more than three,
% then the parsing will die at some point when \handle@accentxx...
% will turn out to be \relax, and then one accent will become an
% argument of another -- too bad.
%
\def\handle@accentxx#1#2#3#4{
% catch more than two accents in a row
\errmessage{Too many accents, dropping first}
#2#3#4
}
% This is simpler now.
%
\def\DeclareTextCompositeCommand#1#2#3#4{
\expandafter\def\csname\expandafter\string\csname
#2\endcsname\string#1-\string#3\endcsname{#4}
}
% This is new.
%
\def\DeclareTextDoubleCompositeCommand#1#2#3#4#5{
\expandafter\def\csname\expandafter\string\csname
#2\endcsname\string#1-\string#3-\string#4\endcsname{#5}
}
% This also.
%
\catcode\z@=11\relax
\def\DeclareTextDoubleComposite#1#2#3#4#5{
\def\reserved@a{\DeclareTextDoubleCompositeCommand#1{#2}{#3}{#4}}
\bgroup
\lccode\z@#5
\lowercase{
\egroup
\reserved@a ^^@}
}
\catcode\z@=15\relax
% Now we reinitialize the \@acc... macros to use our new definitions.
%
\AtBeginDocument{
\let\@acci \'
\let\@accii \`
\let\@acciii \=
}
\endlinechar `\^^M
\endinput
% end of dblaccnt.tex
|