%D \module %D [ file=t-ruby, %D version=2012.03.13, %D title=\CONTEXT\ User Module, %D subtitle=Ruby Markup, %D author=Wolfgang Schuster, %D date=\currentdate, %D copyright=Wolfgang Schuster, %D email=schuster.wolfgang@googlemail.com, %D license=Public Domain] \writestatus{loading}{ConTeXt User Module / Ruby Markup} \unprotect %D simple ruby: %D %D \starttyping %D %D WWW %D World Wide Web %D %D \stoptyping %D %D complex ruby: %D %D \starttyping %D %D %D 10 %D 31 %D 2002 %D %D %D Month %D Day %D Year %D %D %D Expiration Date %D %D %D \stoptyping %D Constants/variables \startinterface all \setinterfaceconstant {basestyle} {basestyle} \setinterfaceconstant {basecolor} {basecolor} \setinterfaceconstant {overhang} {overhang} \setinterfaceconstant {base} {base} \stopinterface \startinterface all \setinterfacevariable {letter} {letter} \setinterfacevariable {end} {end} \setinterfacevariable {inline} {inline} \setinterfacevariable {ruby} {ruby} \stopinterface %D Lua \startluacode thirddata = thirddata or { } thirddata.ruby = thirddata.ruby or { } function thirddata.ruby.doifelsecjk(string) local state = true for c in unicode.utf8.gmatch(string,".") do local n = scripts.hash[utf.byte(c)] if not ( n == "chinese" or n == "korean" ) then state = false break end end commands.doifelse(state) end \stopluacode %D Namespace \installnamespace {ruby} \installnamespace {rubyalign} \installnamespace {rubyalternative} \installnamespace {rubyoverhang} %D Additional registers \newdimen \d_ruby_width \newdimen \d_ruby_base \newdimen \d_ruby_text \newdimen \d_ruby_left \newdimen \d_ruby_right \newdimen \d_ruby_position \newsignal \s_ruby_signal \newcount \c_ruby_n \newtoks \t_ruby_base \newtoks \t_ruby_text \newbox \b_ruby_base \newbox \b_ruby_text \newbox \b_ruby_box %D \macros %D {defineruby,setupruby} \installcommandhandler \????ruby {ruby} \????ruby %D \macros %D {ruby} \unexpanded\def\ruby_cmd#name% {\dontleavehmode \begingroup \edef\currentruby{#name}% \dosingleempty\ruby_cmd_indeed} \unexpanded\def\ruby_cmd_indeed[#parameters]#base#text% {\setupcurrentruby[#parameters,\c!base={#base},\c!text={#text}]% \scratchdimen\lastskip \ifdim\scratchdimen=\s_ruby_signal\else\global\d_ruby_width\zeropoint\fi \global\advance\c_ruby_n\plusone \xypos{rubyposition:\number\c_ruby_n}% \doifmodeelse\v!first {\d_ruby_position\onepoint}% {\d_ruby_position\dimexpr\MPx{rubyposition:\number\c_ruby_n}-\MPx{text:\number\realpageno}\relax}% \setbox\b_ruby_base\hbox{\userubystyleandcolor\c!basestyle\c!basecolor{\directrubyparameter\c!base}}% \setbox\b_ruby_text\hbox{\userubystyleandcolor\c!textstyle\c!textcolor{\directrubyparameter\c!text}}% \d_ruby_base\wd\b_ruby_base \d_ruby_text\wd\b_ruby_text \expandcheckedcsname\????rubyalign {\rubyparameter\c!align }\v!auto \expandcheckedcsname\????rubyalternative{\rubyparameter\c!alternative}\v!top \expandcheckedcsname\????rubyoverhang {\rubyparameter\c!overhang }\v!auto \hskip\s_ruby_signal\relax \endgroup} \appendtoks \setuevalue\currentruby{\ruby_cmd{\currentruby}}% \to \everydefineruby %D Alignment %D %D \startitemize[packed] %D \item left %D \item middle %D \item right %D \item auto %D \item letter %D \item space %D \stopitemize \unexpanded\def\ruby_distribute_space #1{\processtokens{\hss }{\hss\hss}{\hss }{\hss\hss}{#1}} \unexpanded\def\ruby_distribute_letter#1{\processtokens{\relax}{\hss }{\relax}{\hss\hss}{#1}} \setvalue{\????rubyalign\v!space}% stretch? {\d_ruby_left \zeropoint \d_ruby_right\zeropoint \ifdim\d_ruby_base>\d_ruby_text \setbox\b_ruby_base\hbox to \d_ruby_base{\hss\box\b_ruby_base\hss}% \setbox\b_ruby_text\hbox to \d_ruby_base{\userubystyleandcolor\c!textstyle\c!textcolor{\normalexpanded{\ruby_distribute_space{\directrubyparameter\c!text}}}}% \else \setbox\b_ruby_base\hbox to \d_ruby_text{\userubystyleandcolor\c!basestyle\c!basecolor{\normalexpanded{\ruby_distribute_space{\directrubyparameter\c!base}}}}% \setbox\b_ruby_text\hbox to \d_ruby_text{\hss\box\b_ruby_text\hss}% \fi} \setvalue{\????rubyalign\v!letter}% !!! {\d_ruby_left \zeropoint \d_ruby_right\zeropoint \ifdim\d_ruby_base>\d_ruby_test \setbox\b_ruby_base\hbox to \d_ruby_base{\hss\box\b_ruby_base\hss}% \setbox\b_ruby_text\hbox to \d_ruby_base{\userubystyleandcolor\c!textstyle\c!textcolor{\normalexpanded{\ruby_distribute_letter{\directrubyparameter\c!text}}}}% \else \setbox\b_ruby_base\hbox to \d_ruby_text{\userubystyleandcolor\c!basestyle\c!basecolor{\normalexpanded{\ruby_distribute_letter{\directrubyparameter\c!base}}}}% \setbox\b_ruby_text\hbox to \d_ruby_text{\hss\box\b_ruby_text\hss}% \fi} \setvalue{\????rubyalign\v!auto}% {\ifdim\d_ruby_base>\d_ruby_text \ctxlua{thirddata.ruby.doifelsecjk("\directrubyparameter\c!base")}\donetrue\donefalse \ifdone \getvalue{\????rubyalign\v!space}% \else \getvalue{\????rubyalign\v!middle}% \fi \else \ifdim\d_ruby_position=\zeropoint % begin of the line \getvalue{\????rubyalign\v!left}% \else\ifdim\d_ruby_position=\dimexpr\textwidth-\d_ruby_base\relax % end of the line \getvalue{\????rubyalign\v!right}% \else \ctxlua{thirddata.ruby.doifelsecjk("\directrubyparameter\c!text")}\donetrue\donefalse \ifdone \getvalue{\????rubyalign\v!space}% \else \getvalue{\????rubyalign\v!middle}% \fi \fi\fi \fi} \setvalue{\????rubyalign\v!left}% {\ifdim\d_ruby_base>\d_ruby_text \d_ruby_left \zeropoint \d_ruby_right\zeropoint \else \d_ruby_left \zeropoint \d_ruby_right\dimexpr\d_ruby_text-\d_ruby_base\relax \fi \setbox\b_ruby_base\hbox to \d_ruby_base{\box\b_ruby_base\hss}% \setbox\b_ruby_text\hbox to \d_ruby_base{\box\b_ruby_text\hss}} \setvalue{\????rubyalign\v!middle}% {\ifdim\d_ruby_base>\d_ruby_text \d_ruby_left \zeropoint \d_ruby_right\zeropoint \else \d_ruby_left \dimexpr(\d_ruby_text-\d_ruby_base)/2\relax \d_ruby_right\dimexpr(\d_ruby_text-\d_ruby_base)/2\relax \fi \setbox\b_ruby_base\hbox to \d_ruby_base{\hss\box\b_ruby_base\hss}% \setbox\b_ruby_text\hbox to \d_ruby_base{\hss\box\b_ruby_text\hss}} \setvalue{\????rubyalign\v!right}% {\ifdim\d_ruby_base>\d_ruby_base \d_ruby_left \zeropoint \d_ruby_right\zeropoint \else \d_ruby_left \dimexpr\d_ruby_text-\d_ruby_base\relax \d_ruby_right\zeropoint \fi \setbox\b_ruby_base\hbox to \d_ruby_base{\hss\box\b_ruby_base}% \setbox\b_ruby_text\hbox to \d_ruby_base{\hss\box\b_ruby_text}} \setvalue{\????rubyalign\v!margin}% modify to take care of overlap etc. {\ifdim\d_ruby_position=\zeropoint \getvalue{\????rubyalign\v!left}% \else\ifdim\d_ruby_position=\dimexpr\textwidth-\d_ruby_base\relax \getvalue{\????rubyalign\v!right}% \else \getvalue{\????rubyalign\v!middle}% \fi\fi} %D Alternative %D %D \startitemize[packed] %D \item top %D \item bottom %D \item text %D \stopitemize % \setvalue{\????rubyalternative\v!none}% needed for \pdfactualtext % {\directrubyparameter\c!base % \rubyparameter\c!separator % \rubyparameter\c!lefttext % \directrubyparameter\c!text % \rubyparameter\c!righttext} \setvalue{\????rubyalternative\v!top}% {\setbox\b_ruby_box\vbox {\doifsomething{\rubyparameter\c!strut}{\setupstrut[\rubyparameter\c!strut]}% \offinterlineskip \hbox{\undepthed{\begstrut\box\b_ruby_text\endstrut}} \rubyparameter\c!inbetween \hbox{\begstrut\box\b_ruby_base\endstrut}}} \setvalue{\????rubyalternative\v!bottom}% {\setbox\b_ruby_box\vtop {\doifsomething{\rubyparameter\c!strut}{\setupstrut[\rubyparameter\c!strut]}% \offinterlineskip \hbox{\undepthed{\begstrut\box\b_ruby_base\endstrut}} \rubyparameter\c!inbetween \hbox{\begstrut\box\b_ruby_text\endstrut}}} \setvalue{\????rubyalternative\v!text}% pure text to allow line breaks in the text {\setbox\b_ruby_box\box\voidbox \d_ruby_left \zeropoint \d_ruby_right\zeropoint \directrubyparameter\c!base \rubyparameter\c!separator \rubyparameter\c!lefttext\directrubyparameter\c!text\rubyparameter\c!righttext} \unexpanded\def\ruby_alternative_vertical#text% {\setbox\scratchbox\vbox {\userubystyleandcolor\c!textstyle\c!textcolor \setupinterlinespace[\rubyparameter\c!interlinespace]% \handletokens#text\with\hbox \par}% \lower\dimexpr(\ht\scratchbox+\strutdp-\strutht)/2-\rubyparameter\c!dy\relax\box\scratchbox} \setvalue{\????rubyalternative\v!vertical}% {\d_ruby_left \zeropoint \d_ruby_right\zeropoint \setbox\b_ruby_box\hbox\bgroup \begingroup \userubystyleandcolor\c!basestyle\c!basecolor \directrubyparameter\c!base \endgroup \normalexpanded{\ruby_alternative_vertical{\directrubyparameter\c!text}}% \egroup} %D Overhang %D %D \startitemize[packed] %D \item left %D \item right %D \item auto %D \item none %D \stopitemize \setvalue{\????rubyoverhang\v!auto}% {\ifdim\d_ruby_width>\zeropoint \kern\dimexpr\d_ruby_left+\d_ruby_width\relax \fi \box\b_ruby_box \global\d_ruby_width\d_ruby_right} \setvalue{\????rubyoverhang\v!left}% {\box\b_ruby_box\kern\d_ruby_right \global\d_ruby_width\d_ruby_right} \setvalue{\????rubyoverhang\v!right}% {\ifdim\d_ruby_width>\zeropoint \kern\dimexpr\d_ruby_left+\d_ruby_width\relax \else \kern\d_ruby_left \fi \box\b_ruby_box \global\d_ruby_width\zeropoint} \setvalue{\????rubyoverhang\v!none}% {\kern\d_ruby_left\box\b_ruby_box\kern\d_ruby_right \global\d_ruby_width\zeropoint} %D \macros %D {ruby} \defineruby[\v!ruby] %D Default values \setupruby [\c!alternative=\v!top, \c!align=\v!auto, \c!overhang=\v!auto, \c!dy=\zeropoint, \c!separator={ }, \c!lefttext={(}, \c!righttext={)}, \c!strut=\v!no, \c!inbetween={\blank[\v!small]}, \c!textstyle=\txx] \protect \endinput