%D \module %D [ file=page-lin, %D version=2007.11.29, %D title=\CONTEXT\ Core Macros, %D subtitle=Line Numbering, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. % generic or not ... maybe not bother too much and simplify to mkiv only % get rid of \mk* (left over from experimental times) % % to be redone (was experiment) .. can be hooked into margin code \writestatus{loading}{ConTeXt Core Macros / Line Numbering} \unprotect % todo: save settings % % low level interface % % we should use normal counters but then we need to sync settings % some line % % \startlocallinenumbering % some source code 1\par % some source code 2\par % some source code 3\par % \stoplocallinenumbering % % some line \registerctxluafile{page-lin}{1.001} \definesystemattribute[linenumber] [public] \definesystemattribute[linereference][public] \appendtoksonce \attribute\linenumberattribute\attributeunsetvalue \to \everyforgetall \newcount \linenumber % not used \newbox \b_page_lines_scratch \newcount \c_page_lines_reference \newconstant\c_page_lines_nesting \newconditional\tracelinenumbering % we keep this for old times sake \installtextracker {lines.numbers.show} {\settrue \tracelinenumbering} {\setfalse\tracelinenumbering} % id nr shift width leftskip dir \installcorenamespace{linenumberinginstance} \let\makelinenumber\gobblesevenarguments % used at lua end \newconditional\page_postprocessors_needed_box \unexpanded\def\page_postprocessors_linenumbers_page #1{\page_lines_add_numbers_to_box{#1}\plusone \plusone \zerocount} \unexpanded\def\page_postprocessors_linenumbers_box #1{\page_lines_add_numbers_to_box{#1}\plusone \plusone \zerocount} \unexpanded\def\page_postprocessors_linenumbers_deepbox#1{\page_lines_add_numbers_to_box{#1}\plusone \plusone \plusone } \unexpanded\def\page_postprocessors_linenumbers_column #1{\page_lines_add_numbers_to_box{#1}\currentcolumn\nofcolumns\zerocount} \def\page_lines_parameters_regular {continue = "\ifnum\c_page_lines_mode=\zerocount\v!yes\else\v!no\fi", start = \number\linenumberingparameter\c!start, step = \number\linenumberingparameter\c!step, method = "\linenumberingparameter\c!method", tag = "\currentlinenumbering"} \def\page_lines_parameters_update {continue = "\ifnum\c_page_lines_mode=\zerocount\v!yes\else\v!no\fi"} \def\page_lines_start_define {\setxvalue{\??linenumberinginstance\currentlinenumbering}{\ctxcommand{registerlinenumbering({\page_lines_parameters_regular})}}} \def\page_lines_start_update {\ctxcommand{setuplinenumbering(\csname\??linenumberinginstance\currentlinenumbering\endcsname,{\page_lines_parameters_update})}} \def\page_lines_setup {\ifcsname \??linenumberinginstance\currentlinenumbering\endcsname \ctxcommand{setuplinenumbering(\csname\??linenumberinginstance\currentlinenumbering\endcsname,{\page_lines_parameters_regular})}% \fi} % we could make this a bit more efficient by putting the end reference % in the same table as the start one but why make things complex ... \let\dofinishlinereference\dofinishfullreference % at lua end \unexpanded\def\page_lines_some_reference#1#2#3% {\dontleavehmode\begingroup \global\advance\c_page_lines_reference\plusone \attribute\linereferenceattribute\c_page_lines_reference #3% % for the moment we use a simple system i.e. no prefixes etc .. todo: store as number \normalexpanded{\strc_references_set_named_reference{line}{#2}{conversion=\linenumberingparameter\c!conversion}{\the\c_page_lines_reference}}% kind labels userdata text \endgroup} % \def\page_lines_reference_start#1{\page_lines_some_reference{#1}{lr:b:#1}{}} % reimplemented later % \def\page_lines_reference_stop #1{\page_lines_some_reference{#1}{lr:e:#1}{}} % reimplemented later % \def\mklinestartreference#1[#2]{\in{#1}[lr:b:#2]} % not interfaced/ not used % \def\mklinestopreference #1[#2]{\in{#1}[lr:e:#2]} % not interfaced/ not used \newif\ifnumberinglines % will change \newif\iftypesettinglines % will change \installcorenamespace{linenumbering} \installcommandhandler \??linenumbering {linenumbering} \??linenumbering \setnewconstant\c_page_lines_mode \plusone % 0=continue, 1=restart \setnewconstant\c_page_lines_location \plusone % 0=middle, 1=left, 2=right, 3=inner, 4=outer, 5=text, 6=begin, 7=end \setnewconstant\c_page_lines_alignment\plusfive % 0=middle, 1=left, 2=right, 5=auto \newdimen\d_page_lines_width \newdimen\d_page_lines_distance \newevery \beforeeverylinenumbering \relax \newevery \aftereverylinenumbering \relax \newevery \everylinenumber \relax \appendtoks \page_lines_setup \to \everysetuplinenumbering \appendtoks \page_lines_start_define \to \everydefinelinenumbering \setuplinenumbering [\c!conversion=\v!numbers, \c!start=1, \c!step=1, \c!method=\v!first, \c!continue=\v!no, \c!location=\v!left, \c!style=, \c!color=, \c!width=2\emwidth, \c!left=, \c!right=, \c!command=, \c!distance=\zeropoint, \c!align=\v!auto] \definelinenumbering [] % no intermediate changes in values, define a class, otherwise each range % would need a number % todo: text \installcorenamespace{linenumberinglocation} \installcorenamespace{linenumberingalternative} \expandafter\let\csname\??linenumberinglocation\v!middle \endcsname \zerocount \expandafter\let\csname\??linenumberinglocation\v!left \endcsname \plusone \expandafter\let\csname\??linenumberinglocation\v!margin \endcsname \plusone \expandafter\let\csname\??linenumberinglocation\v!inmargin \endcsname \plusone \expandafter\let\csname\??linenumberinglocation\v!inleft \endcsname \plusone \expandafter\let\csname\??linenumberinglocation\v!right \endcsname \plustwo \expandafter\let\csname\??linenumberinglocation\v!inright \endcsname \plustwo \expandafter\let\csname\??linenumberinglocation\v!inner \endcsname \plusthree \expandafter\let\csname\??linenumberinglocation\v!outer \endcsname \plusfour \expandafter\let\csname\??linenumberinglocation\v!text \endcsname \plusfive \expandafter\let\csname\??linenumberinglocation\v!begin \endcsname \plussix \expandafter\let\csname\??linenumberinglocation\v!end \endcsname \plusseven \expandafter\let\csname\??linenumberingalternative\v!middle \endcsname \zerocount \expandafter\let\csname\??linenumberingalternative\v!right \endcsname \plusone \expandafter\let\csname\??linenumberingalternative\v!flushleft \endcsname \plusone \expandafter\let\csname\??linenumberingalternative\v!left \endcsname \plustwo \expandafter\let\csname\??linenumberingalternative\v!flushright\endcsname \plustwo \expandafter\let\csname\??linenumberingalternative\v!auto \endcsname \plusfive % \startlinenumbering[|continue|settings|name] % \startlinenumbering[name][|continue|settings] \unexpanded\def\startlinenumbering {\dodoubleempty\page_lines_start} \def\page_lines_start % we stay downward compatible {\begingroup \ifsecondargument \expandafter\page_lines_start_two \else\iffirstargument \doubleexpandafter\page_lines_start_one \else \doubleexpandafter\page_lines_start_zero \fi\fi} \def\page_lines_start_zero[#1][#2]% {\edef\m_argument{\linenumberingparameter\c!continue}% \ifx\m_argument\v!continue \c_page_lines_mode\zerocount \else \c_page_lines_mode\plusone \fi \page_lines_start_followup} \def\page_lines_start_one[#1][#2]% [continue||settings] % historic {\edef\m_argument{#1}% \ifx\m_argument\v!continue \c_page_lines_mode\zerocount \let\currentlinenumbering\empty \else \c_page_lines_mode\plusone \ifx\m_argument\v!empty \let\currentlinenumbering\empty \else \doifassignmentelse{#1} {\let\currentlinenumbering\empty \setupcurrentlinenumbering[#1]} {\doifnumberelse\m_argument {\let\currentlinenumbering\empty \letlinenumberingparameter\c!start\m_argument} {\let\currentlinenumbering\m_argument}}% \fi \edef\p_continue{\linenumberingparameter\c!continue}% \ifx\p_continue\v!yes \c_page_lines_mode\zerocount \fi \fi \page_lines_start_followup} \def\page_lines_start_two[#1][#2]% [tag][continue||settings] {\edef\currentlinenumbering{#1}% \edef\m_argument{#2}% \ifx\m_argument\v!continue \c_page_lines_mode\zerocount \else \c_page_lines_mode\plusone \ifx\m_argument\v!empty \else \doifassignmentelse{#2} {\setupcurrentlinenumbering[#2]} {\doifnumber\m_argument {\letlinenumberingparameter\c!start\m_argument}}% \fi \edef\p_continue{\linenumberingparameter\c!continue}% \ifx\p_continue\v!yes \c_page_lines_mode\zerocount \fi \fi \page_lines_start_followup} \def\page_lines_start_followup {\numberinglinestrue \the\beforeeverylinenumbering \globallet\page_postprocessors_page \page_postprocessors_linenumbers_page \globallet\page_postprocessors_column\page_postprocessors_linenumbers_column \global\settrue\page_postprocessors_needed_box % see core-rul.mkiv \ifcase\c_page_lines_mode\relax \page_lines_start_update % continue \or \page_lines_start_define % only when assignment \fi \attribute\linenumberattribute\getvalue{\??linenumberinginstance\currentlinenumbering}\relax} \unexpanded\def\stoplinenumbering {\attribute\linenumberattribute\attributeunsetvalue \the\aftereverylinenumbering \endgroup} % number placement .. will change into (the new) margin code \def\page_lines_number_inner_indeed{\doifoddpageelse\page_lines_number_left_indeed\page_lines_number_right_indeed} \def\page_lines_number_outer_indeed{\doifoddpageelse\page_lines_number_right_indeed\page_lines_number_left_indeed} \def\page_lines_number_left {\ifcase\c_page_lines_location \expandafter\page_lines_number_left_indeed \or \expandafter\page_lines_number_left_indeed \or \expandafter\page_lines_number_left_indeed \or \expandafter\page_lines_number_inner_indeed \or \expandafter\page_lines_number_outer_indeed \or \expandafter\page_lines_number_text_indeed \or \expandafter\page_lines_number_begin_indeed \or \expandafter\page_lines_number_end_indeed \fi} \def\page_lines_number_right {\ifcase\c_page_lines_location \expandafter\page_lines_number_right_indeed \or \expandafter\page_lines_number_right_indeed \or \expandafter\page_lines_number_right_indeed \or \expandafter\page_lines_number_outer_indeed \or \expandafter\page_lines_number_inner_indeed \or \expandafter\page_lines_number_text_indeed \or \expandafter\page_lines_number_end_indeed \or \expandafter\page_lines_number_begin_indeed \fi} \newconditional\c_page_lines_fake_number \newconstant \b_page_lines_number \newconstant \c_page_lines_column \newconstant \c_page_lines_last_column \def\page_lines_add_numbers_to_box#1#2#3#4% box col max nesting {\bgroup \b_page_lines_number #1\relax \c_page_lines_column #2\relax \c_page_lines_last_column#3\relax \c_page_lines_nesting #4\relax \fullrestoreglobalbodyfont \let\makelinenumber\page_lines_make_number % used at lua end \setbox\b_page_lines_scratch\vbox {\forgetall \offinterlineskip \ctxcommand{linenumbersstageone(\number\b_page_lines_number,\ifcase\c_page_lines_nesting false\else true\fi)}}% \ctxcommand{linenumbersstagetwo(\number\b_page_lines_number,\number\b_page_lines_scratch)}% can move to lua code \egroup} \let\page_lines_make_number_indeed\relax \def\page_lines_make_number#1#2% {\edef\currentlinenumbering{#1}% \ifcase#2\relax \settrue \c_page_lines_fake_number \else \setfalse\c_page_lines_fake_number \fi \c_page_lines_location \executeifdefined{\??linenumberinglocation \linenumberingparameter\c!location}\plusone \relax % left \c_page_lines_alignment\executeifdefined{\??linenumberingalternative\linenumberingparameter\c!align }\plusfive\relax % auto \ifcase\c_page_lines_last_column\relax \settrue \c_page_lines_fake_number \or % one column \ifcase\c_page_lines_location \settrue \c_page_lines_fake_number \let\page_lines_make_number_indeed\page_lines_number_fake_indeed \or \let\page_lines_make_number_indeed\page_lines_number_left \or \let\page_lines_make_number_indeed\page_lines_number_right \or % inner \let\page_lines_make_number_indeed\page_lines_number_inner_indeed \or % outer \let\page_lines_make_number_indeed\page_lines_number_outer_indeed \or % text \let\page_lines_make_number_indeed\page_lines_number_text_indeed \or \let\page_lines_make_number_indeed\page_lines_number_begin_indeed \or \let\page_lines_make_number_indeed\page_lines_number_end_indeed \fi \else\ifcase\c_page_lines_column\relax \settrue \c_page_lines_fake_number \or \let\page_lines_make_number_indeed\page_lines_number_left \ifcase\c_page_lines_location\or \c_page_lines_location\plusone \or \c_page_lines_location\plustwo \else \c_page_lines_location\plusone \or \c_page_lines_location\plusone \or \c_page_lines_location\plusone \or \c_page_lines_location\plusone % todo \or \c_page_lines_location\plusone % todo \fi \else \let\page_lines_make_number_indeed\page_lines_number_right \ifcase\c_page_lines_location\or \c_page_lines_location\plustwo \or \c_page_lines_location\plusone \or \c_page_lines_location\plustwo \or \c_page_lines_location\plustwo \or \c_page_lines_location\plustwo % todo \or \c_page_lines_location\plustwo % todo \fi \fi\fi \page_lines_make_number_indeed{#1}} \let\page_lines_number_fake_indeed\gobblesixarguments % needs checking \def\page_lines_number_text_indeed#1#2#3#4#5#6% beware, one needs so compensate for this in the \hsize {\hbox{\page_lines_number_construct{#1}{2}{#2}{#5}\hskip#3\scaledpoint}} \def\page_lines_number_left_indeed#1#2#3#4#5#6% {\naturalhbox to \zeropoint {\ifcase\istltdir#6\else \hskip-#4\scaledpoint \fi \llap{\page_lines_number_construct{#1}{2}{#2}{#5}\kern#3\scaledpoint}}} \def\page_lines_number_right_indeed#1#2#3#4#5#6% {\naturalhbox to \zeropoint {\ifcase\istltdir#6\else \hskip-#4\scaledpoint \fi \rlap{\hskip\dimexpr#4\scaledpoint+#3\scaledpoint\relax\page_lines_number_construct{#1}{1}{#2}{#5}}}} \def\page_lines_number_begin_indeed#1#2#3#4#5#6% {\ifcase\istltdir#6\relax \c_page_lines_location\plusone \expandafter\page_lines_number_left_indeed \else \c_page_lines_location\plustwo \expandafter\page_lines_number_left_indeed \fi{#1}{#2}{#3}{#4}{#5}{#6}} \def\page_lines_number_end_indeed#1#2#3#4#5#6% {\ifcase\istltdir#6\relax \c_page_lines_location\plustwo \expandafter\page_lines_number_left_indeed \else \c_page_lines_location\plusone \expandafter\page_lines_number_left_indeed \fi{#1}{#2}{#3}{#4}{#5}{#6}} \def\page_lines_number_construct#1#2#3#4% tag 1=left|2=right linenumber leftskip {\begingroup \def\currentlinenumbering{#1}% \def\linenumber{#3}% unsafe \doifelse{\linenumberingparameter\c!width}\v!margin {\d_page_lines_width\leftmarginwidth} {\d_page_lines_width\linenumberingparameter\c!width}% \d_page_lines_distance\linenumberingparameter\c!distance\relax \ifcase#2\relax\or\hskip\d_page_lines_distance\fi\relax \ifnum\c_page_lines_location=\plusfive \scratchdimen\dimexpr#4\scaledpoint-\d_page_lines_distance\relax \c_page_lines_location\plusone \else \scratchdimen\zeropoint \fi \ifcase\c_page_lines_alignment \c_page_lines_location\zerocount % middle \or \c_page_lines_location\plusone % left \or \c_page_lines_location\plustwo % right \fi \ifconditional\tracelinenumbering\ruledhbox\else\hbox\fi to \d_page_lines_width {\ifcase\c_page_lines_location \hss % middle \or % left \or \hss % right \or \doifoddpageelse\relax\hss % inner \or \doifoddpageelse\hss\relax % outer \fi \ifconditional\c_page_lines_fake_number % we need to reserve space \else \uselinenumberingstyleandcolor\c!style\c!color \linenumberingparameter\c!command {\linenumberingparameter\c!left \convertnumber{\linenumberingparameter\c!conversion}{#3}% \linenumberingparameter\c!right}% \fi \ifcase\c_page_lines_location \hss % middle \or \hss % left \or % right \or \doifoddpageelse\hss\relax % inner \or \doifoddpageelse\relax\hss % outer \fi}% \ifcase#2\relax \hskip-\scratchdimen \or \hskip-\scratchdimen \or \hskip\dimexpr\d_page_lines_distance-\scratchdimen\relax \fi \relax \the\everylinenumber \endgroup} % referencing: \permithyphenation, also removes leading spaces (new per 29-11-2013) \unexpanded\def\someline [#1]{\page_lines_reference_start{#1}\page_lines_reference_stop{#1}} % was just a def \unexpanded\def\startline[#1]{\page_lines_reference_start{#1}\ignorespaces} \unexpanded\def\stopline [#1]{\removeunwantedspaces\permithyphenation\page_lines_reference_stop{#1}} \def\page_lines_reference_show_start {\ifconditional\tracelinenumbering \expandafter\page_lines_reference_show_start_indeed \else \expandafter\gobbleoneargument \fi} \def\page_lines_reference_show_stop {\ifconditional\tracelinenumbering \expandafter\page_lines_reference_show_stop_indeed \else \expandafter\gobbleoneargument \fi} \def\page_lines_reference_show_start_indeed#1% {\setbox\scratchbox\hbox{\llap {\vrule\s!width\onepoint\s!depth\strutdp\s!height.8\strutht\raise.85\strutht\hbox{\llap{\tt\txx#1}}}}% \smashbox\scratchbox \box\scratchbox} \def\page_lines_reference_show_stop_indeed#1% {\setbox\scratchbox\hbox{\rlap {\raise.85\strutht\hbox{\rlap{\tt\txx#1}}\vrule\s!width\onepoint\s!depth\strutdp\s!height.8\strutht}}% \smashbox\scratchbox \box\scratchbox} \def\page_lines_reference_start#1{\page_lines_some_reference{#1}{lr:b:#1}{\page_lines_reference_show_start{#1}}} \def\page_lines_reference_stop #1{\page_lines_some_reference{#1}{lr:e:#1}{\page_lines_reference_show_stop {#1}}} % eventually we will do this in lua \def\currentreferencelinenumber{\ctxcommand{filterreference("linenumber")}} \let\m_page_lines_from\empty \let\m_page_lines_to \empty \unexpanded\def\doifelsesamelinereference#1#2#3% {\doifreferencefoundelse{lr:b:#1} {\edef\m_page_lines_from{\currentreferencelinenumber}% \doifreferencefoundelse{lr:e:#1} {\edef\m_page_lines_to{\currentreferencelinenumber}% %[\m_page_lines_from,\m_page_lines_to] \ifx\m_page_lines_from\m_page_lines_to#2\else#3\fi} {#2}} {#2}} \unexpanded\def\inline#1[#2]% {\doifelsenothing{#1} {\doifelsesamelinereference{#2} {\in{\leftlabeltext\v!line}{\rightlabeltext\v!line}[lr:b:#2]} {\in{\leftlabeltext\v!lines}{}[lr:b:#2]--\in{}{\rightlabeltext\v!lines}[lr:e:#2]}} {\doifelsesamelinereference{#2} {\in{#1}[lr:b:#2]} {\in{#1}[lr:b:#2]--\in[lr:e:#2]}}} \unexpanded\def\inlinerange[#1]% {\doifelsesamelinereference{#1} {\in[lr:b:#1]} {\in[lr:b:#1]\endash\in[lr:e:#1]}} \protect \endinput