typo-del.mkxl /size: 30 Kb    last modification: 2025-02-21 11:03
1%D \module
2%D   [       file=typo-del, % moved from core-mis,
3%D        version=20110112,
4%D          title=\CONTEXT\ Typesetting Macros,
5%D       subtitle=Delimited Content,
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% todo: textstyle|color for inline \quotation etc
15
16\writestatus{loading}{ConTeXt Typesetting Macros / Delimited Content}
17
18\unprotect
19
20\ifdefined\dotagsetdelimitedsymbol   \else \aliased\let\dotagsetdelimitedsymbol  \gobbleoneargument \fi
21\ifdefined\dotagsetsubsentencesymbol \else \aliased\let\dotagsetsubsentencesymbol\gobbleoneargument \fi
22
23% Kind of special ...
24
25\installcorenamespace{hyphenmarksign} % let's not waste a setuphandler (yet)
26
27\permanent\permanent\protected\def\setuphyphenmark[#1]% sign=normal|wide
28  {\getdummyparameters[#1]%
29   \expandnamespaceparameter\??hyphenmarksign\dummyparameter\c!sign\v!normal}
30
31\defcsname\??hyphenmarksign\v!normal\endcsname
32  {\enforced\let\textmodehyphen\normalhyphen
33   \enforced\let\textmodehyphendiscretionary\normalhyphendiscretionary}
34
35\defcsname\??hyphenmarksign\v!wide\endcsname
36  {\enforced\let\textmodehyphen\composedhyphen
37   \enforced\let\textmodehyphendiscretionary\composedhyphendiscretionary}
38
39\setuphyphenmark[\c!sign=\v!wide]
40
41\definesymbol[\c!lefthyphen]  [\languageparameter\c!lefthyphen]
42\definesymbol[\c!righthyphen] [\languageparameter\c!righthyphen]
43\definesymbol[\c!hyphen]      [\languageparameter\c!hyphen]
44
45\permanent\protected\def\normalhyphen
46  {\hbox{\directsymbol\empty\c!hyphen}}
47
48\permanent\protected\def\composedhyphen
49  {\hbox{\directsymbol\empty\c!compoundhyphen}}
50
51\permanent\protected\def\normalhyphendiscretionary
52  {\discretionary
53     {\hbox{\directsymbol\empty\c!righthyphen}}
54     {\hbox{\directsymbol\empty\c!lefthyphen}}
55     {\hbox{\directsymbol\empty\c!hyphen}}}
56
57\permanent\protected\def\composedhyphendiscretionary
58  {\discretionary
59     {\hbox{\directsymbol\empty\c!rightcompoundhyphen}}
60     {\hbox{\directsymbol\empty\c!leftcompoundhyphen}}
61     {\hbox{\directsymbol\empty\c!compoundhyphen}}}
62
63\aliased\let\textmodehyphen             \composedhyphen
64\aliased\let\textmodehyphendiscretionary\composedhyphendiscretionary
65
66\definesymbol[\c!leftcompoundhyphen]  [\languageparameter\c!leftcompoundhyphen]
67\definesymbol[\c!rightcompoundhyphen] [\languageparameter\c!rightcompoundhyphen]
68\definesymbol[\c!compoundhyphen]      [\languageparameter\c!compoundhyphen]
69
70\immutable\integerdef\compoundhyphencode\privatecharactercode{compoundhyphen}
71
72\pushoverloadmode
73
74\permanent\protected\def\compoundhyphenfont
75  {\char\compoundhyphencode}                 % tuned for font
76
77\permanent\protected\def\compoundhyphenfake
78  {\char\hyphenasciicode
79  %\kern-.10775\emwidth                      % mkiv (.25\exheight)
80  %\kern-.5\fontcharwd\font\hyphenasciicode  % for a while
81   \kern{-\fontcharwd\font\hyphenasciicode/3}% okay for most
82   \char\hyphenasciicode}
83
84\permanent\protected\def\compoundhyphen
85  {\hbox\bgroup
86     \iffontchar\font\compoundhyphencode
87       \compoundhyphenfont
88     \else
89       \compoundhyphenfake
90     \fi
91   \egroup}
92
93\popoverloadmode
94
95% ... till here.
96
97\setnewconstant\boundarycharactermode\plusone
98
99% old:       skip symbol skip
100% new: bound skip symbol skip bound
101
102\permanent\protected\def\midboundarycharacter#1#2%
103  {\ifcase\boundarycharactermode
104   \or
105     \removeunwantedspaces
106     \wordboundary
107     \hskip\hspaceamount\currentusedlanguage{#2}%
108     \usedlanguageparameter#1%
109     \hskip\hspaceamount\currentusedlanguage{#2}%
110     \wordboundary
111     \ignorespaces
112   \or
113     \usedlanguageparameter#1%
114   \fi
115   \boundarycharactermode\plusone}
116
117% old: symbol nobreak skip
118% new: symbol nobreak skip wordboundary
119
120\permanent\protected\def\leftboundarycharacter#1#2%
121  {\ifcase\boundarycharactermode
122   \or
123     \usedlanguageparameter#1%
124     \nobreak
125     \hskip\hspaceamount\currentusedlanguage{#2}% why not a kern
126     \wordboundary
127   \or
128     \usedlanguageparameter#1%
129   \fi
130   \boundarycharactermode\plusone}
131
132% old: preword         skip symbol
133% new: bound   nobreak skip symbol
134
135\permanent\protected\def\rightboundarycharacter#1#2%
136  {\ifcase\boundarycharactermode
137   \or
138     \wordboundary
139     \nobreak
140     \hskip\hspaceamount\currentusedlanguage{#2}% why not a kern
141     \usedlanguageparameter#1%
142   \or
143     \usedlanguageparameter#1%
144   \fi
145   \boundarycharactermode\plusone}
146
147\definehspace [sentence]      [\zeropoint]
148\definehspace [intersentence] [.250\emwidth]
149
150\definesymbol
151  [\c!midsentence]
152  [\midboundarycharacter\c!midsentence{sentence}]
153
154\definesymbol
155  [\c!leftsentence]
156  [\leftboundarycharacter\c!leftsentence{sentence}]
157
158\definesymbol
159  [\c!rightsentence]
160  [\rightboundarycharacter\c!rightsentence{sentence}]
161
162\definesymbol
163  [\c!leftsubsentence]
164  [\leftboundarycharacter\c!leftsubsentence{sentence}]
165
166\definesymbol
167  [\c!rightsubsentence]
168  [\rightboundarycharacter\c!rightsubsentence{sentence}]
169
170\newinteger\c_typo_subsentence_nesting
171
172\mutable\let\beforesubsentence\donothing % maybe just a parameter
173\mutable\let\aftersubsentence \donothing % maybe just a parameter
174
175% todo: make this language option
176%
177% \def\beforesubsentence{\removeunwantedspaces}
178% \def\aftersubsentence {\ignorespaces}
179
180\newconditional\c_typo_subsentence_cleanup  \c_typo_subsentence_cleanup\conditionaltrue
181
182\def\typo_subsentence_cleanup_start
183  {\ifconditional\c_typo_subsentence_cleanup
184     \expandafter\ignorespaces
185   \fi}
186
187\def\typo_subsentence_cleanup_stop
188  {\ifconditional\c_typo_subsentence_cleanup
189     \removeunwantedspaces
190   \fi}
191
192\permanent\protected\def\midsentence
193  {\dostarttaggednodetail\t!subsentencesymbol
194   \dotagsetsubsentencesymbol\s!middle
195   \symbol[\c!midsentence]%
196   \dostoptagged}
197
198\newboundary\c_typo_subsentence_boundary
199
200\permanent\protected\def\beginofsubsentence
201  {\beforesubsentence
202   \ifnum\lastboundary=\c_typo_subsentence_boundary
203     \unboundary
204     \kern\hspaceamount\currentusedlanguage{intersentence}%
205   \fi
206   \global\advanceby\c_typo_subsentence_nesting\plusone
207   \ifnum\c_typo_subsentence_nesting=\plusone
208     \dontleavehmode
209   \fi
210   \dostarttaggednodetail\t!subsentence
211   \dostarttaggednodetail\t!subsentencesymbol
212   \dotagsetsubsentencesymbol\s!left
213   \symbol[\ifodd\c_typo_subsentence_nesting\c!leftsentence\else\c!leftsubsentence\fi]%
214   \dostoptagged
215   \dostarttaggednodetail\t!subsentencecontent
216   \typo_subsentence_cleanup_start}
217
218\permanent\protected\def\endofsubsentence % relax prevents space gobbling
219  {\typo_subsentence_cleanup_stop
220   \dostoptagged
221   \dostarttaggednodetail\t!subsentencesymbol
222   \dotagsetsubsentencesymbol\s!right
223   \symbol[\ifodd\c_typo_subsentence_nesting\c!rightsentence\else\c!rightsubsentence\fi]%
224   \dostoptagged
225   \dostoptagged
226   \global\advanceby\c_typo_subsentence_nesting\minusone
227   \unskip
228   \boundary\c_typo_subsentence_boundary
229   \aftersubsentence}
230
231\permanent\protected\def\beginofsubsentencespacing % relax prevents space gobbling
232  {\boundary\c_typo_subsentence_boundary}% \ignorespaces}
233
234\permanent\protected\def\endofsubsentencespacing
235  {\ifnum\lastboundary=\c_typo_subsentence_boundary
236     \unboundary
237     \hskip\hspaceamount\currentusedlanguage{intersentence}%
238     % no good, actually language dependent:
239     % \ignorespaces
240   \else
241     \unskip
242   \fi}
243
244%D \startbuffer
245%D test |<|test |<|test|>| test|>| test \par
246%D test|<|test|<|test|>|test|>|test \par
247%D test |<||<|test|>||>| test \par
248%D test \directdiscretionary{<}test\directdiscretionary{>} test \par
249%D \stopbuffer
250%D
251%D \typebuffer
252%D \getbuffer
253
254\permanent\protected\def\startsubsentence{\beginofsubsentence\wordboundary\beginofsubsentencespacing\wordboundary\typo_subsentence_cleanup_start}
255\permanent\protected\def\stopsubsentence {\typo_subsentence_cleanup_stop\wordboundary\endofsubsentencespacing\wordboundary\endofsubsentence}
256\permanent\protected\def\subsentence     {\groupedcommandcs\startsubsentence\stopsubsentence}
257\permanent\protected\def\midsubsentence  {\typo_subsentence_cleanup_start\wordboundary\midsentence\wordboundary\typo_subsentence_cleanup_stop}
258
259\definehspace [quotation]      [\zeropoint]
260\definehspace [interquotation] [.125em]
261
262%definehspace [quote]  [\zeropoint]
263%definehspace [speech] [\zeropoint]
264
265\definehspace [quote]  [\hspaceamount\currentusedlanguage{quotation}]
266\definehspace [speech] [\hspaceamount\currentusedlanguage{quotation}]
267
268\definesymbol
269  [\c!leftquotation]
270  [\leftboundarycharacter\c!leftquotation{quotation}]
271
272\definesymbol
273  [\c!rightquotation]
274  [\rightboundarycharacter\c!rightquotation{quotation}]
275
276\definesymbol
277  [\c!nextleftquotation]
278  [\rightboundarycharacter\c!leftquotation{quotation}]
279
280\definesymbol
281  [\c!nextrightquotation]
282  [\leftboundarycharacter\c!rightquotation{quotation}]
283
284\definesymbol
285  [\c!leftquote]
286  [\leftboundarycharacter\c!leftquote{quote}]
287
288\definesymbol
289  [\c!rightquote]
290  [\rightboundarycharacter\c!rightquote{quote}]
291
292\definesymbol
293  [\c!leftspeech]
294  [\leftboundarycharacter\c!leftspeech{speech}]
295
296\definesymbol
297  [\c!rightspeech]
298  [\rightboundarycharacter\c!rightspeech{speech}]
299
300\definesymbol
301  [\c!middlespeech]
302  [\leftboundarycharacter\c!middlespeech{speech}]
303
304\appendtoks
305    \enforced\permanent\def\quotation#1{"#1"}%
306    \enforced\permanent\def\quote    #1{'#1'}%
307\to \everysimplifycommands
308
309%D The next features was so desperately needed by Giuseppe Bilotta that he made a
310%D module for it. Since this is a typical example of core functionality, I decided
311%D to extend the low level quotation macros in such a way that a speech feature
312%D could be build on top of it. The speech opening and closing symbols are defined
313%D per language. Italian is an example of a language that has them set.
314
315\mutable\let\currentdelimitedtext      \s!unknown
316\mutable\let\currentparentdelimitedtext\currentdelimitedtext
317
318\installglobalmacrostack\currentdelimitedtext
319
320\mutable\let\delimitedtextlevel\!!zerocount
321
322\permanent\def\c_typo_delimited_nesting{\csname\??delimitedtextlevel\currentparentdelimitedtext\endcsname}
323
324% the \setlanguageparameter macro sets but we are ungrouped .. only used here
325%
326% \currentusedlanguage
327% \usedlanguageparameter
328
329%D The optional argument can be a language, a narrower spec, or a outer:inner language
330%D specification.
331%D
332%D \starttabulate
333%D     \NC [en]    \NC {\tttf en} \quotation[en]   {{\tttf <en=\currentlanguage>} something french} \NC \NR
334%D     \NC [fr]    \NC {\tttf en} \quotation[fr]   {{\tttf <fr=\currentlanguage>} something french} \NC \NR
335%D     \NC [fr:]   \NC {\tttf fr} \quotation[fr:]  {{\tttf <en=\currentlanguage>} something french} \NC \NR
336%D     \NC [:fr]   \NC {\tttf en} \quotation[:fr]  {{\tttf <fr=\currentlanguage>} something french} \NC \NR
337%D     \NC [fr:fr] \NC {\tttf fr} \quotation[fr:fr]{{\tttf <fr=\currentlanguage>} something french} \NC \NR
338%D     \NC [en:fr] \NC {\tttf en} \quotation[en:fr]{{\tttf <fr=\currentlanguage>} something french} \NC \NR
339%D     \NC [fr:en] \NC {\tttf fr} \quotation[fr:en]{{\tttf <en=\currentlanguage>} something french} \NC \NR
340%D \stoptabulate
341
342\mutable\lettonothing\currentdelimitedlanguage
343\mutable\lettonothing\innerdelimitedlanguage
344\mutable\lettonothing\outerdelimitedlanguage
345
346\installglobalmacrostack\currentdelimitedlanguage
347
348\def\typo_delimited_set_language_nop
349  {\setusedlanguage{\delimitedtextparameter\c!language}}
350
351\def\typo_delimited_set_language_yes
352  {\doiflanguageelse\m_delimited_argument
353     \typo_delimited_set_language_yes_a
354     {\doifelseinstring:\m_delimited_argument
355        \typo_delimited_set_language_yes_b
356        \typo_delimited_set_language_nop}}
357
358\def\typo_delimited_set_language_yes_b
359  {\splitatcolon\m_delimited_argument\outerdelimitedlanguage\innerdelimitedlanguage
360   \ifempty\outerdelimitedlanguage
361     \typo_delimited_set_language_nop
362   \else
363     \doiflanguageelse\outerdelimitedlanguage
364       {\setusedlanguage\outerdelimitedlanguage}%
365       \typo_delimited_set_language_nop
366   \fi
367   \ifempty\innerdelimitedlanguage\else
368     \doiflanguageelse\innerdelimitedlanguage
369       {\let\currentdelimitedlanguage\innerdelimitedlanguage}%
370       \donothing
371   \fi
372   \lettonothing\m_delimited_argument}
373
374\def\typo_delimited_set_language_yes_a
375  {\let\currentdelimitedlanguage\m_delimited_argument
376   \lettonothing\m_delimited_argument}
377
378\def\typo_delimited_push#1#2%
379  {\push_macro_currentdelimitedtext     % can we combine these two
380   \push_macro_currentdelimitedlanguage % the language used for hyphenation
381   \cdef\currentdelimitedtext{#1}%
382   \edef\m_delimited_argument{#2}%
383   \ifempty\m_delimited_argument
384     \typo_delimited_set_language_nop
385   \else
386     \typo_delimited_set_language_yes
387   \fi
388   \let\currentparentdelimitedtext\currentdelimitedtext
389   \global\advanceby\c_typo_delimited_nesting\plusone
390   \edef\delimitedtextlevel{\the\c_typo_delimited_nesting}%
391   \normalexpanded{\chaintocurrentdelimitedtext{\currentparentdelimitedtext:\delimitedtextlevel}}%
392   \cdef\currentdelimitedtext{\currentparentdelimitedtext:\delimitedtextlevel}}
393
394\def\typo_delimited_pop
395  {\global\advanceby\c_typo_delimited_nesting\minusone
396   \pop_macro_currentdelimitedlanguage
397   \pop_macro_currentdelimitedtext}
398
399\installcorenamespace{delimitedtext}
400\installcorenamespace{delimitedtextlevel}
401
402\installcommandhandler \??delimitedtext {delimitedtext} \??delimitedtext
403
404\appendtoks
405    \expandafter\newinteger\csname\??delimitedtextlevel\currentdelimitedtext\endcsname
406    \frozen\instance\protected\edefcsname\currentdelimitedtext        \endcsname{\delimitedtext[\currentdelimitedtext]}%
407    \frozen\instance\protected\edefcsname\e!start\currentdelimitedtext\endcsname{\startdelimitedtext[\currentdelimitedtext]}%
408    \frozen\instance\protected\edefcsname\e!stop \currentdelimitedtext\endcsname{\stopdelimitedtext}%
409\to \everydefinedelimitedtext
410
411\setupdelimitedtext
412  [\c!location=\v!margin, % \v!text \v!paragraph
413   \c!spacebefore=,
414   \c!spaceafter=\delimitedtextparameter\c!spacebefore,
415   \c!style=,
416   \c!color=,
417   \c!leftmargin=\zeropoint,
418   \c!rightmargin=\delimitedtextparameter\c!leftmargin,
419   \c!indentnext=\v!yes,
420   \c!before=,
421   \c!after=,
422   \c!left=,
423   \c!right=,
424  %\c!level=0,
425   \c!method=,
426  %\c!language=\v!local,
427   \c!repeat=\v!no]
428
429\def\typo_delimited_repeat_indeed
430  {\relax\ifcase\delimitedtextlevel\else
431     \typo_delimited_handle_middle\c!middle
432   \fi}
433
434\lettonothing\typo_delimited_repeat
435
436\permanent\tolerant\protected\def\startdelimitedtext[#1]#*[#2]%
437  {\begingroup
438   \typo_delimited_push{#1}{#2}%
439   \dostarttaggedchained\t!delimitedblock\currentparentdelimitedtext\currentdelimitedtext\??delimitedtext
440   \edef\p_method{\delimitedtextparameter\c!method}%
441   \ifx\p_method\v!font
442     \expandafter\typo_delimited_start_font
443   \orelse\ifx\p_method\v!paragraph
444     \expandafter\typo_delimited_start_font
445   \else
446     \expandafter\typo_delimited_start_other
447   \fi}
448
449\let\typo_delimited_stop\relax % hooks into \everypar
450
451\def\typo_delimited_start_font
452  {\let\typo_delimited_stop\typo_delimitedtexts_finish_font
453   \dostarttaggednodetail\t!delimitedsymbol
454   \dotagsetdelimitedsymbol\s!left
455   \delimitedtextparameter\c!left
456   \dostoptagged
457   \ignorespaces}
458
459\newconditional\c_typo_delimited_repeating
460
461\def\typo_delimited_start_other
462  {\edef\p_delimited_repeat{\delimitedtextparameter\c!repeat}%
463   \ifx\p_delimited_repeat\v!yes
464     \let\typo_delimited_repeat\typo_delimited_repeat_indeed
465   \else
466     \lettonothing\typo_delimited_repeat
467   \fi
468   \c_typo_delimited_repeating\conditionalfalse
469   \edef\p_delimited_location{\delimitedtextparameter\c!location}%
470   \ifx\p_delimited_location\v!paragraph
471     \expandafter\typo_delimited_start_par
472   \orelse\ifx\p_delimited_location\v!margin
473     \expandafter\typo_delimited_start_par
474   \else
475     \expandafter\typo_delimited_start_txt
476   \fi}
477
478\def\typo_delimitedtexts_finish_font
479  {\removeunwantedspaces % again ?
480   \dostarttaggednodetail\t!delimitedsymbol
481   \dotagsetdelimitedsymbol\s!right
482   \delimitedtextparameter\c!right
483   \dostoptagged}
484
485\def\typo_delimited_show_language_indeed#1#2%
486  {\begingroup
487   \infofont
488   \setbox\scratchbox\hpack{\lower\strutht\hbox to \zeropoint{\darkred#1\currentlanguage:\currentdelimitedlanguage#2}}%
489   \vsmashbox\scratchbox
490   \box\scratchbox
491   \endgroup}
492
493\let\typo_delimited_show_language\gobbletwoarguments
494
495\installtextracker{delimited.language}
496  {\let\typo_delimited_show_language\typo_delimited_show_language_indeed}
497  {\let\typo_delimited_show_language\gobbletwoarguments}
498
499\def\typo_delimited_start_content
500  {\dostarttaggednodetail\t!delimitedcontent
501   \begingroup
502   \douselanguageparameter\currentdelimitedlanguage
503   \typo_delimited_show_language<\hss
504   \ignorespaces}
505
506\def\typo_delimited_stop_content
507  {\removeunwantedspaces
508   \removelastskip % redundant
509   \typo_delimited_show_language\hss<%
510   \endgroup
511   \dostoptagged}
512
513\lettonothing\p_delimited_left
514\lettonothing\p_delimited_right
515\lettonothing\p_delimited_nextleft
516\lettonothing\p_delimited_nextright
517
518\tolerant\def\typo_delimited_start_par[#1]%
519  {\let\typo_delimited_stop\typo_delimited_stop_par
520   \checkedblank[\delimitedtextparameter\c!spacebefore]%
521   \delimitedtextparameter\c!before
522   \edef\m_delimited_argument{#1}%
523   \ifempty\m_delimited_argument
524     \let\m_delimited_argument\m_delimited_argument
525   \fi
526   \ifempty\m_delimited_argument
527     \endgraf
528     \doadaptleftskip {\delimitedtextparameter\c!leftmargin}%
529     \doadaptrightskip{\delimitedtextparameter\c!rightmargin}%
530     \let\typo_delimited_stop_par_indeed\endgraf
531   \else % backward compatible direct directive
532     \startnarrower[\m_delimited_argument]%
533     \let\typo_delimited_stop_par_indeed\stopnarrower
534   \fi
535   % so far
536   \push_macro_checkindentation
537   \useindentingparameter\delimitedtextparameter
538   %
539   \begingroup
540   \usedelimitedtextstyleandcolor\c!style\c!color
541   %
542   \begingroup
543   \usealignparameter\delimitedtextparameter
544   \edef\p_delimited_left     {\delimitedtextparameter\c!left}%
545   \edef\p_delimited_right    {\delimitedtextparameter\c!right}%
546   \edef\p_delimited_nextleft {\delimitedtextparameter\c!nextleft}%
547   \edef\p_delimited_nextright{\delimitedtextparameter\c!nextright}%
548   %
549   \leftdelimitedtextmark
550   %
551   \setnextleftdelimitedtextmark
552   \setnextrightdelimitedtextmark
553   %
554   \typo_delimited_start_content}
555
556\let\typo_delimited_stop_par_indeed\endgraf
557
558\def\typo_delimited_stop_par
559  {\typo_delimited_stop_content
560   \rightdelimitedtextmark
561   \carryoverpar\endgroup
562   \endgraf
563   \endgroup
564   \pop_macro_checkindentation
565   \typo_delimited_stop_par_indeed
566   \delimitedtextparameter\c!after
567   \checkedblank[\delimitedtextparameter\c!spaceafter]%
568   \useindentnextparameter\delimitedtextparameter
569   \aftergroup\dorechecknextindentation}% AM: This was missing!
570
571\def\typo_delimited_start_txt
572  {\let\typo_delimited_stop\typo_delimited_stop_txt
573   \begingroup
574   \usedelimitedtextstyleandcolor\c!style\c!color
575   \typo_delimited_handle_left\c!left
576   \typo_delimited_start_content}
577
578\def\typo_delimited_stop_txt
579  {\typo_delimited_stop_content
580   \typo_delimited_handle_right\c!right
581   \endgroup}
582
583\permanent\protected\def\stopdelimitedtext
584  {\typo_delimited_stop
585   \dostoptagged
586   \typo_delimited_pop
587   \endgroup}
588
589\permanent\tolerant\protected\def\delimitedtext[#1]#*[#2]%
590  {\dontleavehmode % following ones can be omited
591   \typo_delimited_push{#1}{#2}%
592   \edef\p_method{\delimitedtextparameter\c!method}%
593   \ifx\p_method\v!font
594     \expandafter\typo_delimited_fontdriven
595   \orelse\ifx\p_method\v!text
596     \expandafter\typo_delimited_fontdriven
597   \else
598     \expandafter\typo_delimited_other
599   \fi}
600
601\def\typo_delimited_other
602  {\edef\p_delimited_location{\delimitedtextparameter\c!location}%
603   \ifx\p_delimited_location\v!paragraph
604     \expandafter\typo_delimited_par
605   \orelse\ifx\p_delimited_location\v!margin
606     \expandafter\typo_delimited_par
607   \else
608     \expandafter\typo_delimited_txt
609   \fi}
610
611% shortcuts
612
613\permanent\protected\def\startdelimited{\startdelimitedtext}
614\permanent\protected\def\stopdelimited {\stopdelimitedtext}  % no let, dynamically assigned
615\permanent          \def\delimited     {\delimitedtext}
616
617% todo: \dostarttaggednodetail\t!nothing % for left/right boxes
618
619%D We have 4 different location and symbol handlers (two pairs):
620%D
621%D \starttyping
622%D \input tufte \startquotation \input tufte \stopquotation
623%D
624%D \setupdelimitedtext
625%D   [quotation]
626%D   [nextleft=right,
627%D    nextright=left]
628%D
629%D \input tufte \startquotation \input tufte \stopquotation
630%D
631%D \setupdelimitedtext
632%D   [quotation]
633%D   [nextleft={\symbol[nextleftquotation]},
634%D    nextright={\symbol[nextrightquotation]}]
635%D
636%D \input tufte \startquotation \input tufte \stopquotation
637%D \stoptyping
638
639\permanent\protected\def\setnextleftdelimitedtextmark
640  {\ifempty\p_delimited_nextleft
641      % nothing
642   \orelse\ifx\p_delimited_nextleft\v!left
643     \typo_delimited_nextleft_symbol\p_delimited_left
644   \orelse\ifx\p_delimited_nextleft\v!right
645     \typo_delimited_nextleft_symbol\p_delimited_right
646   \else
647     \typo_delimited_nextleft_symbol\p_delimited_nextleft
648   \fi}
649
650\permanent\protected\def\setnextrightdelimitedtextmark
651  {\ifempty\p_delimited_nextright
652      % nothing
653   \orelse\ifx\p_delimited_nextright\v!right
654     \typo_delimited_nextright_symbol\p_delimited_right
655   \orelse\ifx\p_delimited_nextright\v!left
656     \typo_delimited_nextright_symbol\p_delimited_left
657   \else
658     \typo_delimited_nextright_symbol\p_delimited_nextright
659   \fi}
660
661\permanent\protected\def\leftdelimitedtextmark
662  {\ifempty\p_delimited_left
663      % nothing
664   \else
665     \typo_delimited_left_symbol\p_delimited_left
666   \fi}
667
668\permanent\protected\def\rightdelimitedtextmark
669  {\ifempty\p_delimited_right
670      % nothing
671   \else
672      \typo_delimited_right_symbol\p_delimited_right
673   \fi}
674
675\def\typo_delimited_left_symbol#1%
676  {% a hack: we need to make sure that the par counter is incremented for tagging / export
677   \dontleavehmode
678   % oterwise we get a break because the symbol has a different par number
679   \dostarttaggednodetail\t!delimitedsymbol
680   \dotagsetdelimitedsymbol\s!left
681   \setbox\scratchbox\hbox{\usedelimitedtextstyleandcolor\c!symstyle\c!symcolor#1}%
682   \dontleavehmode
683   \edef\p_delimited_margin{\delimitedtextparameter\c!location}%
684   \ifx\p_delimited_margin\v!margin
685      \kern-\wd\scratchbox
686   \fi
687   \unhbox\scratchbox
688   \dostoptagged}
689
690\def\typo_delimited_right_symbol#1%
691  {\dostarttaggednodetail\t!delimitedsymbol
692   \dotagsetdelimitedsymbol\s!right
693   \hsmash{\usedelimitedtextstyleandcolor\c!symstyle\c!symcolor#1}%
694   \dostoptagged}
695
696\def\typo_delimited_nextleft_symbol#1%
697  {\let\typo_delimited_reset_next_symbol\typo_delimited_reset_next_symbol_indeed
698   \localleftbox\bgroup
699     \enforced\swapmacros\leftboundarycharacter\rightboundarycharacter
700     \boundarycharactermode\plusone
701     \typo_delimited_left_symbol#1%
702   \egroup}
703
704\def\typo_delimited_nextright_symbol#1%
705  {\let\typo_delimited_reset_next_symbol\typo_delimited_reset_next_symbol_indeed
706   \localrightbox\bgroup
707     \enforced\swapmacros\leftboundarycharacter\rightboundarycharacter
708     \boundarycharactermode\plusone
709     \typo_delimited_right_symbol#1%
710   \egroup}
711
712\protected\def\typo_delimited_reset_next_symbol_indeed
713  {\localleftbox {}%
714   \localrightbox{}}%
715
716\let\typo_delimited_reset_next_symbol\relax
717
718\appendtoks
719    \typo_delimited_reset_next_symbol
720\to \everyforgetall
721
722% \starttext
723%    \hyphenatedword{groepsvrijstellingsverordeningen}\par
724%    \hyphenatedword{\quote{groepsvrijstellingsverordeningen}}\par
725%     \dorecurse{100}{\hskip300pt\hskip\recurselevel pt test \quote{xxx xxxx}.\par}
726%     \page \setuppapersize[A5][A4]
727%     \quotation {overly beautiful pusillanimous sesquipedalian
728%     longwinded} test test test test test test test test test test test
729%     test test test test test test test test test test test test test
730%     test test test test test test test test test test test test test
731%     test test test test test test test test test test test test test
732%     test test test
733% \stoptext
734
735% We have no real test case for this and it's broken already for a while,
736% even in \MKII. Maybe we should to this in \LUA. Only Italian has the
737% middlespeech parameter set.
738
739\newboundary\c_typo_delimited_boundary
740
741\def\typo_delimited_handle_middle#1% special case
742  {\ifconditional\c_typo_delimited_repeating
743     \begingroup
744     \usedelimitedtextstyleandcolor\c!symstyle\c!symcolor
745     \setbox\scratchbox\hbox{\delimitedtextparameter#1}%
746     \ifdim\wd\scratchbox>\zeropoint
747       \ifnum\lastboundary=\c_typo_delimited_boundary
748         \unboundary
749         \hskip\hspaceamount\currentusedlanguage{interquotation}%
750       \else % maybe an option:
751        %\edef\p_delimited_margin{\delimitedtextparameter\c!location}%
752        %\ifx\p_delimited_margin\v!margin
753        %   \hskip-\wd\scratchbox
754        %\fi
755       \fi
756       \strut % new, needed below
757       \dostarttaggednodetail\t!delimitedsymbol
758       \dotagsetdelimitedsymbol\s!middle
759       \delimitedtextparameter#1% unhbox\scratchbox
760       \dostoptagged
761     % \penalty\plustenthousand % else overfull boxes, but that's better than dangling periods
762       \boundary\c_typo_delimited_boundary
763     \fi
764     \endgroup
765   \else
766     \c_typo_delimited_repeating\conditionaltrue
767   \fi}
768
769\def\typo_delimited_handle_left#1%
770  {\begingroup
771   \usedelimitedtextstyleandcolor\c!symstyle\c!symcolor
772   \setbox\scratchbox\hbox{\delimitedtextparameter#1}%
773   \ifdim\wd\scratchbox>\zeropoint
774     \ifnum\lastboundary=\c_typo_delimited_boundary
775       \unboundary
776       \hskip\hspaceamount\currentusedlanguage{interquotation}%
777     \fi
778   % \strut % new, needed below
779   % \ifhmode % else funny pagebeaks
780   %   \penalty\plustenthousand
781   %   \hskip\zeroskip % == \prewordbreak
782   % \fi
783     \strut % new, needed below
784     \dostarttaggednodetail\t!delimitedsymbol
785     \dotagsetdelimitedsymbol\s!left
786     \delimitedtextparameter#1% unhbox\scratchbox
787     \dostoptagged
788     \boundary\c_typo_delimited_boundary
789   \fi
790   \endgroup}
791
792\def\typo_delimited_handle_right#1%
793  {\begingroup
794   \usedelimitedtextstyleandcolor\c!symstyle\c!symcolor
795   \setbox\scratchbox\hbox{\delimitedtextparameter#1}%
796   \ifdim\wd\scratchbox>\zeropoint
797     \ifnum\lastboundary=\c_typo_delimited_boundary
798       \unboundary
799       \penalty\plustenthousand
800       \hskip\hspaceamount\currentusedlanguage{interquotation}%
801     \fi
802     \ifhmode % else funny pagebeaks
803       \penalty\plustenthousand
804       \hskip\zeroskip % == \prewordbreak
805     \fi
806     \strut % new, needed below
807     \dostarttaggednodetail\t!delimitedsymbol
808     \dotagsetdelimitedsymbol\s!right
809     \delimitedtextparameter#1% unhbox\scratchbox
810     \dostoptagged
811     \boundary\c_typo_delimited_boundary
812   \fi
813   \endgroup}
814
815\protected\def\typo_delimited_par
816  {\groupedcommand
817     {\dostarttaggedchained\t!delimited\currentparentdelimitedtext\currentdelimitedtext\??delimitedtext % block?
818      \usedelimitedtextstyleandcolor\c!style\c!color
819      \typo_delimited_handle_left\c!left
820      \typo_delimited_start_content}
821     {\typo_delimited_stop_content
822      \typo_delimited_handle_right\c!right
823      \removelastskip % hm
824      \dostoptagged
825      \typo_delimited_pop}}
826
827\protected\def\typo_delimited_txt
828  {\edef\p_left_right{\delimitedtextparameter\c!left\delimitedtextparameter\c!right}%
829   \ifempty\p_left_right
830     \expandafter\typo_delimited_attributed
831   \else
832     \expandafter\typo_delimited_quoted
833   \fi}
834
835\def\typo_delimited_quoted
836  {\dontleavehmode
837   \begingroup
838   \dostarttaggedchained\t!delimited\currentparentdelimitedtext\currentdelimitedtext\??delimitedtext
839   \usedelimitedtextstyleandcolor\c!style\c!color
840   \typo_delimited_handle_left\c!left
841   \typo_delimited_start_content
842   \bgroup
843   \aftergroup\typo_delimited_quoted_e
844   \let\next=}
845
846\def\typo_delimited_quoted_e
847  {\typo_delimited_stop_content
848   \typo_delimited_handle_right\c!right
849   \removelastskip % ?
850   \dostoptagged
851   \typo_delimited_pop
852   \endgroup}
853
854\def\typo_delimited_attributed
855  {\dontleavehmode
856   \begingroup
857   \dostarttaggedchained\t!delimited\currentparentdelimitedtext\currentdelimitedtext\??delimitedtext
858   \usedelimitedtextstyleandcolor\c!style\c!color
859   \typo_delimited_start_content
860   \bgroup
861   \aftergroup\typo_delimited_attributed_e
862   \let\next=}
863
864\def\typo_delimited_attributed_e
865  {\typo_delimited_stop_content
866   \dostoptagged
867   \typo_delimited_pop
868   \endgroup}
869
870\def\typo_delimited_fontdriven
871  {\dontleavehmode
872   \begingroup
873   \dostarttaggedchained\t!delimited\currentparentdelimitedtext\currentdelimitedtext\??delimitedtext
874   \usedelimitedtextstyleandcolor\c!style\c!color
875   \usedlanguageparameter{\c!left\currentparentdelimitedtext}% was: \currentdelimitedtext
876   \typo_delimited_start_content
877   \bgroup
878   \aftergroup\typo_delimited_fontdriven_e
879   \let\next=}
880
881\def\typo_delimited_fontdriven_e
882  {\typo_delimited_stop_content
883   \usedlanguageparameter{\c!right\currentparentdelimitedtext}% was: \currentdelimitedtext
884   \dostoptagged
885   \typo_delimited_pop
886   \endgroup}
887
888% testcase for nesting:
889%
890% \quotation{... \quotation{...} ...}
891% \startquotation ... \startquotation... \quotation{...} \stopquotation\space ...\stopquotation
892% \setupdelimitedtext[quotation][1][left=(,right=)]
893% \setupdelimitedtext[quotation][2][left={[},right={]}]
894% \setupdelimitedtext[quotation][3][left=\{,right=\}]
895% \quotation{... \quotation{...} ...}
896% \startquotation ... \startquotation... \quotation{...} \stopquotation\space ...\stopquotation
897
898\definedelimitedtext
899  [\v!quotation]
900  [\c!left={\symbol[\c!leftquotation]},
901   \c!right={\symbol[\c!rightquotation]},
902   \c!leftmargin=\v!standard]
903
904\definedelimitedtext
905  [\v!quote][\v!quotation]
906
907\setupdelimitedtext
908  [\v!quote]
909  [\c!location=\v!text,
910   \c!left={\symbol[\c!leftquote]},
911   \c!right={\symbol[\c!rightquote]}]
912
913\definedelimitedtext
914   [\v!blockquote][\v!quotation]
915
916\setupdelimitedtext
917  [\v!blockquote]
918  [\c!left=,
919   \c!right=]
920
921\definedelimitedtext
922  [\v!speech][\v!quotation]
923
924\setupdelimitedtext
925  [\v!speech]
926  [\c!repeat=\v!yes,
927   \c!left={\symbol[\c!leftspeech]},
928   \c!middle={\symbol[\c!middlespeech]},
929   \c!right={\symbol[\c!rightspeech]}]
930
931\definedelimitedtext
932  [\v!aside]
933  [\c!left={\symbol[\c!leftsentence]},
934   \c!right={\symbol[\c!rightsentence]}]
935
936% how do we call an tight quote
937%
938% \definedelimitedtext
939%    [\v!quotation][\v!quotation]
940%
941% \setupdelimitedtext
942%   [\v!quotation]
943%   [\c!indentnext=\v!no,
944%    \c!spacebefore=\v!nowhite]
945
946\permanent\protected\def\setupquotation{\setupdelimitedtext[\v!quotation]}
947\permanent\protected\def\setupquote    {\setupdelimitedtext[\v!quote]}
948
949\protect \endinput
950