%D \module %D [ file=t-bib, %D version=2005.01.04, %D title=\CONTEXT\ Publication Module, %D subtitle=Publications, %D author=Taco Hoekwater, %D date=\currentdate, %D copyright=Public Domain] %C %C Donated to the public domain. \usemodule[bibltx] % bibtex files can contain latex left-overs %D Slightly adapted by HH (2005/01). For \BIBTEX\ relate questions, %D contact Taco, if you expect interference with core macros, bother %D Hans. This file will be cleaned up in due time. %D %D Documentation and additional resources can be found at %D Taco's website: \url{tex.aanhet.net}. %D \subject{DONE} %D %D \startitemize %D \item minor bugfixes today (25/6) %D \item add finalnamesep support for Oxford comma (17/9) %D \item add \insert... for: doi, eprint, howpublished (17-19/9) %D \item minor fix (26/5/2004): %D \item add author definition (and associated system variable) %D \stopitemize %D \subject{TODO} %D %D \startitemize %D \item export \type {\citation{}} %D \item export a \type {\bibalternative{lastpubsep}} from BST instead of 'and' %D \item don't reset [numbercommand] in \type {\setuppublication} by default %D \item sort out different APS versions: PR A/B/L vs. RPM %D \item (implement sub-options? / \type {\setupcitationstyle} ?) %D \item worry about localization at same time %D \item add hyperlinking to the doi->URL and \type {\cite}->list, in general %D \item don't load the whole lot, but filter entries instead %D \stopitemize \unprotect %D A few new shortcuts: \definesystemvariable {pv} % PublicationVariable \definesystemvariable {pb} % PuBlication \definemessageconstant {bib} \definefileconstant {bibextension} {bbl} %D Some user information messages. \startmessages all library: bib title: publications 1: file -- not found, unknown style ignored 2: file -- not found, don't forget to run bibtex 3: wrote a new auxiliary file \jobname.aux 4: loading database from -- 5: warning: cite argument -- on \the\inputlineno 6: loading formatting style from -- \stopmessages %D Some constants for the multi-lingual interface \startconstants dutch english database: database database sorttype: sorttype sorttype compress: compress compress autohang: autohang autohang % author: author author artauthor: artauthor artauthor editor: editor editor authoretallimit: authoretallimit authoretallimit artauthoretallimit: artauthoretallimit artauthoretallimit editoretallimit: editoretallimit editoretallimit authoretaldisplay: authoretaldisplay authoretaldisplay artauthoretaldisplay: artauthoretaldisplay artauthoretaldisplay editoretaldisplay: editoretaldisplay editoretaldisplay authoretaltext: authoretaltext authoretaltext artauthoretaltext: artauthoretaltext artauthoretaltext editoretaltext: editoretaltext editoretaltext totalnumber: totalnumber totalnumber firstnamesep: firstnamesep firstnamesep vonsep: vonsep vonsep juniorsep: juniorsep juniorsep surnamesep: surnamesep surnamesep lastnamesep: lastnamesep lastnamesep finalnamesep: finalnamesep finalnamesep namesep: namesep namesep pubsep: pubsep pubsep lastpubsep: lastpubsep lastpubsep refcommand: refcommand refcommand samplesize: samplesize samplesize \stopconstants \startvariables dutch english german czech italian romanian title: titel title titel titul titolo titlu short: kort short kurz short short short cite: cite cite cite cite cite cite bbl: bbl bbl bbl bbl bbl bbl bib: bib bib bib bib bib bib author: auteur author autor autor autore autor \stopvariables %D The text string for the publication list header \setupheadtext[en][pubs=References] \setupheadtext[nl][pubs=Literatuur] \setupheadtext[de][pubs=Literatur] %D \macros{bibdoifelse} %D %D Here is a really small helper that is used a lot (which is why it %D makes sense to use \type{\ifx} instead of \type{\doif..}). %D This test is used in all the typesetting commands %D (\type{\insert...}) we will encounter later. \def\bibdoifelse#1% {\ifx#1\relax \@EA\secondoftwoarguments \else\ifx#1\empty \@EAEAEA\secondoftwoarguments \else \@EAEAEA\firstoftwoarguments \fi\fi} \def\bibdoif#1% {\ifx#1\relax \@EA\gobbleoneargument \else\ifx#1\empty \@EAEAEA\gobbleoneargument \else \@EAEAEA\firstofoneargument \fi\fi} \def\bibdoifnot#1% {\ifx#1\relax \@EA\firstofoneargument \else\ifx#1\empty \@EAEAEA\firstofoneargument \else \@EAEAEA\gobbleoneargument \fi\fi} %D Bibtex settings separated out %D No point in writing the aux file if there is no database... \def\setupbibtex{\dosingleempty\dosetupbibtex} \def\dosetupbibtex[#1]% {\let\@@pbdatabase\empty \let\@@pbsort \empty \getparameters[\??pb][#1] \expanded{\processaction[\@@pbsort]} [ \v!no=>\def\bibstyle{cont-no}, \v!author=>\def\bibstyle{cont-au}, \v!title=>\def\bibstyle{cont-ti}, \v!short=>\def\bibstyle{cont-ab}, \s!default=>\def\bibstyle{cont-no}, \s!unknown=>\def\bibstyle{cont-no}]% \ifx\@@pbdatabase\empty\else \writeauxfile \fi} %D \macros{writeauxfile} %D %D Unfortunately, \BIBTEX\ is not the best configurable program %D around. The names of the commands it parses as well as the \type{.aux} %D extension to the file name are both hardwired. %D %D This means \CONTEXT\ has to write a \LATEX-style auxiliary file, yuk! %D The good news is that it can be rather short. We'll just ask %D \BIBTEX\ to output the entire database(s) into the \type{bbl} file. %D %D The \type{\bibstyle} command controls how the \type{bbl} file will %D be sorted. The possibilities are: %D %D \startitemize[packed] %D \item by author (+year, title): cont-au.bst %D \item by title (+author, year): cont-ti.bst %D \item by short key as in abbrev.bst: cont-ab.bst %D \item not sorted at all: cont-no.bst %D \stopitemize \def\writeauxfile {\openout \scratchwrite \jobname.aux \write \scratchwrite {\string\citation{*}}% \write \scratchwrite {\string\bibstyle{\bibstyle}}% \write \scratchwrite {\string\bibdata{\@@pbdatabase}}% \closeout\scratchwrite \showmessage\m!bib{3}{}} %D \macros{ifsortbycite,iftypesetall,ifautohang,ifbibcitecompress} %D %D The module needs some new \type{\if} statements. %D Default sort order of the reference list is by citation. \newif\ifsortbycite \sortbycitetrue %D By default, only referenced publications are typeset \newif\iftypesetall \typesetallfalse %D Hanging indentation of the publication list %D will not adjust itself according to the width of the label. \newif\ifautohang \autohangfalse %D Cite lists are compressed, if possible. \newif\ifbibcitecompress \bibcitecompresstrue \def\setuppublications {\dosingleargument\dosetuppublications} \def\bibleftnumber#1% {#1\hfill~} \def\dosetuppublications[#1]% {\getparameters [\??pb] [\c!numbercommand=\bibleftnumber,\c!alternative=,#1]% \doifsomething\@@pbalternative {\readsysfile{bibl-\@@pbalternative.tex} {\showmessage\m!bib{6}{bibl-\@@pbalternative}\let\@@pbalternative\empty} {\showmessage\m!bib{1}{bibl-\@@pbalternative}\let\@@pbalternative\empty}}% \doifnothing{\@@pbalternative} {\processaction [\@@pbcriterium] [ \v!all=>\typesetalltrue, \s!unknown=>\typesetallfalse]% \processaction [\@@pbautohang] [ \v!yes=>\autohangtrue, \s!unknown=>\autohangfalse]% \processaction [\@@pbsorttype] [ \v!cite=>\sortbycitetrue, \v!bbl=>\sortbycitefalse, \s!default=>\sortbycitetrue, \s!unknown=>\sortbycitefalse]% \processaction [\@@pbnumbering] [ \v!yes=>\let\@@pbinumbercommand\firstofoneargument, \v!no=>\let\@@pbinumbercommand\gobbleoneargument, \v!short=>\def\@@pbinumbercommand##1{\@@pbs}, \v!bib=>\def\@@pbinumbercommand##1{\@@pbn}, \s!unknown=>\let\@@pbinumbercommand\firstofoneargument]% \processaction [\@@pbrefcommand] [\s!default=>\edef\@@citedefault{\@@pbrefcommand}, \s!unknown=>\edef\@@citedefault{\@@pbrefcommand}]}} % initialize \def\@@pbrefcommand{num} %D how to load the references: \appendtoks \dousepublications\jobname \to \everystarttext %D \macros{usepublications} %D %D We need \type{\usereferences} so that it is possible to %D refer to page and/or appearance number for publications %D in the other document. \def\usepublications[#1]% {\usereferences[#1]\processcommalist[#1]\dousepublications} \def\dousepublications#1% {\readsysfile{#1.\f!bibextension} {\showmessage\m!bib{4}{#1.\f!bibextension}} {\showmessage\m!bib{2}{#1.\f!bibextension}}} %D \macros{setuppublicationlist} %D %D This will be the first command in (\BIBTEX-generated) \type{bbl} %D files. `samplesize' is a sample value (in case of \BIBTEX-generated %D files, this will be the longest `short' key). `totalnumber' %D is the total number of entries that will follow in this %D file. %D Both values are only needed for the label calculation %D if `autohang' is `true', so by default the command is %D not even needed, and therefore I saw no need to give %D it it's own system variable and it just re-uses \type{pb}. \def\setuppublicationlist {\dosingleempty\dosetuppublicationlist} \definelist[pubs][pubs] \def\dosetuppublicationlist[#1]% {\getparameters [@@pvdata] [\c!samplesize={AA99},\c!totalnumber={99},#1]% for sample & totalnumber & firstnamesep etc. \setuplist [pubs] [\c!alternative=a,\c!pagenumber=\v!no,#1]} \def\setuppublicationlayout[#1]% {\setvalue{@@pvdata#1}} %D \macros{bibalternative} %D %D A nice little shorthand that will be used so we don't have to %D key in the weird \type{\@@pv} parameter names all the time. \def\bibalternative#1% {\getvalue{\??pv\@@currentalternative#1}} %D \macros{simplebibdef,bibcommandlist} %D %D \type{\simplebibdef} defines \type{bib@#1}, which in turn will %D use one argument that is stored in \type{@@pb@#1}. %D %D \type{\simplebibdef} also defines \type{insert#1}, which can be %D used in the argument of \type{\setuppublicationlayout} to fetch %D one of the \type{@@pb@} data entries. \type{insert#1} then has %D three arguments: \type{#1} are commands to be executed before the %D data, \type{#2} are commands to be executed after the data, and %D \type{#3} are commands to be executed if the data is not found. %D \type{\bibcommandlist} is the list of commands that is affected %D by this approach. Later on, it will be used to do a series %D of assignments from \type{#1} to \type{bib@#1}: e.g %D \type{\title} becomes \type{\bib@title} when used within %D a publication. \def\simplebibdef#1% hh: funny expansion ? {\@EA\long\@EA\def\csname bib@#1\endcsname##1% {\setvalue{\??pb @#1}{##1}\ignorespaces}% \@EA\def\csname insert#1\endcsname##1##2##3% {\@EA\bibdoifelse \@EA{\csname @@pb@#1\endcsname}% {##1\csname @@pb@#1\endcsname##2}% {##3}}} \def\bibcommandlist {arttitle,title,journal,notes, volume,issue,pubname,city,country, type,organization,institute,series,thekey, edition,month,pubyear,note,annotate,pages, keyword,keywords,comment,abstract,names,size, issn,isbn,chapter,eprint,doi,howpublished} \processcommacommand[\bibcommandlist]\simplebibdef \def\newbibfield[#1]% {\simplebibdef{#1}% \edef\bibcommalist{\bibcommandlist,#1}} %D \macros{bib@crossref} %D %D \type{\crossref} is used in database files to point to another %D entry. Because of this special situation, it has to be defined %D separately. Since this command will not be seen until at %D \type{\placepublications}, it may force extra runs. The same is %D true for \type{\cite} commands inside of publications. \def\bib@crossref#1% {\setvalue{\??pb @crossref}{#1}\ignorespaces} \def\insertcrossref#1#2#3% {\bibdoifelse{\@@pb@crossref} {#1\@EA\cite\@EA[\@@pb@crossref]#2} {#3}} %D \macros{complexbibdef,specialbibinsert} %D %D The commands \type{\artauthor}, \type{\author} and %D \type{\editor} are more complex than the other commands. %D Their argument lists have this form: %D %D \type{\author[junior]{firstnames}[inits]{von}{surname}} %D %D (bracketed stuff should become optional someday) %D %D And not only that, but there also might be more than one of each of %D these commands. This is why a special command is needed to insert %D them, as well as one extra counter for each command. %D All of these \type{\@EA}'s and \type{\csnames} make this code %D look far more complex than it really is. For example, the argument %D \type{author} defines the macro \type{\bib@author} to do two %D things: increment the counter \type{\author@num} (let's say to 2) %D and next store it's arguments in the macro \type{\@@pb@author2}. %D And it defines \type{\insertauthors} to expand into %D \starttypen %D \specialbibinsert{author}{\author@num}{}{}{} %D \stoptypen % hh: use a context counter instead, more options \def\complexbibdef#1% {\@EA\newcounter\csname #1@num\endcsname \@EA\def\csname bib@#1\endcsname[##1]##2[##3]##4##5% {\@EA\increment\csname #1@num\endcsname \setvalue{\??pb @#1\csname #1@num\endcsname}% {{##2}{##4}{##5}{##3}{##1}}\ignorespaces}% \@EA\def\csname insert#1s\endcsname##1##2##3% {\specialbibinsert{#1}{\csname #1@num\endcsname}{##1}{##2}{##3}}} \processcommalist[author,artauthor,editor]\complexbibdef %D Another level of indirection is needed to control the %D typesetting of all of these arguments, which explains the usage %D of \type{\tempa} below. %D There is some sneaky stuff with \type{\tempa} and \type{\tempb} %D going on here to resolve the \type{\csname}'s. It probably could %D be done a little bit more elegant, but it works. The basic goal %D is to get the command that will actually typeset the name into %D the macro \type{\tempb}, and to make sure that that command will actually %D recieve five arguments (see the definition of %D e.g. \type{\invertedauthor} below). %D There is a conflict between `author' and the predefined interface %D variable `auteur'. The old version is overruled `auteur' is %D overruled by the systemconstant definition at the top of this file! %D The increment/decrement trick on \type{\scratchcounter} is needed %D to decide what name the last one is. \newcount\etallimitcounter \newcount\etaldisplaycounter \newcount\todocounter \def\specialbibinsert#1#2#3#4#5% {\bgroup \ifnum#2>\zerocount \letcscsname\tempa\csname @@pvdata#1\endcsname \def\tempb{\@EA\tempa}% \etallimitcounter =0\bibalternative{#1etallimit}\relax \etaldisplaycounter=0\bibalternative{#1etaldisplay}\relax \ifnum #2>\etallimitcounter \todocounter\etaldisplaycounter % just in case ... \ifnum\todocounter>\etallimitcounter \todocounter\etallimitcounter \fi \else \todocounter#2\relax \fi \scratchcounter\zerocount \ifnum\todocounter>\zerocount #3% \doloop {\ifnum \scratchcounter < \todocounter \advance\scratchcounter \plusone \ifnum \scratchcounter = \todocounter \@EA\tempb \csname @@pb@#1\the\scratchcounter\endcsname \ifnum\etallimitcounter<#2 \bibalternative{#1etaltext}\fi #4% \else \@EA\tempb \csname @@pb@#1\the\scratchcounter\endcsname \advance\scratchcounter \plusone \ifnum \scratchcounter = \todocounter \ifnum \todocounter > \plustwo \bibalternative\c!finalnamesep \else \bibalternative\c!lastnamesep \fi \else \bibalternative\c!namesep \fi \advance\scratchcounter \minusone \fi \else \exitloop \fi}% \else #5% \fi \else #5% \fi \egroup} %D \macros{invertedauthor,normalauthor,invertedshortauthor,normalshortauthor} %D %D Just some commands that can be used in \type{\setuppublicationparameters} %D If you want to write an extension to the styles, you might %D as well define some of these commands yourself. %D %D The argument liust has been reordered here, and the meanings %D are: %D %D {\obeylines\parskip0pt %D \type{#1} firstnames %D \type{#2} von %D \type{#3} surname %D \type{#4} inits %D \type{#5} junior %D } %D \def\invertedauthor#1#2#3#4#5% {\bibdoif{#2}{#2\bibalternative\c!vonsep}% #3\bibalternative\c!surnamesep \bibdoif{#5}{#5\bibalternative\c!juniorsep}% \bibdoif{#1}{#1\unskip}} \def\normalauthor#1#2#3#4#5% {\bibdoif{#1}{#1\bibalternative\c!firstnamesep}% \bibdoif{#2}{#2\bibalternative\c!vonsep}% #3\bibalternative\c!surnamesep \bibdoif{#5}{#5\unskip}} \def\invertedshortauthor#1#2#3#4#5% {\bibdoif{#2}{#2\bibalternative\c!vonsep}% #3\bibalternative\c!surnamesep \bibdoif{#5}{#5\bibalternative\c!juniorsep}% \bibdoif{#4}{#4\unskip}} \def\normalshortauthor#1#2#3#4#5% {\bibdoif{#4}{#4\bibalternative\c!firstnamesep}% \bibdoif{#2}{#2\bibalternative\c!vonsep}% #3\bibalternative\c!surnamesep \bibdoif{#5}{#5\unskip}} %D \macros{clearbibitem,clearbibitemtwo,bibitemdefs} %D %D These are used in \type{\typesetapublication} to do %D initializations and cleanups. \def\clearbibitem#1{\setvalue{\??pb @#1}{}}% \def\clearbibitemtwo#1% {\letvalue{#1@num}\!!zerocount \scratchcounter\plusone \doloop {\doifdefinedelse{\??pb @#1\the\scratchcounter} {\letvalue{\??pb @#1\the\scratchcounter}\empty \advance\scratchcounter\plusone}% {\exitloop}}} \def\bibitemdefs#1{\setvalue{#1}{\csname bib@#1\endcsname}} %D \macros{startpublication} %D %D We are coming to the end of this module, to the macros that %D do typesetting and read the \type{bbl} file. %D %D The stuff between \type{\startpublication} ... \type{\stoppublication} %D is simply stored into a macro: either %D \type{\publist} (potentially huge) or separate macros %D for each of them, depending on whether %D or not we do \type{\sortbycite}, as explained above. \newcounter\bibcounter %D Just a \type{\dosingleempty} is the most friendly %D of doing this: there need not even be an argument %D to \type{\startpublication}. Of course, then there %D is no key either, and it had better be an %D article (otherwise the layout will be all screwed up). \def\startpublication{\dosingleempty\dostartpublication} \def\stoppublication {} %D Only specifying the key in the argument is also %D legal. In storing this stuff into macros, some trickery with %D token registers is needed to fix the expansion problems. Even so, %D this appears to not always be 100\% safe, so people are %D urgently advised to use \ETEX\ instead of traditional \TEX. %D %D In \ETEX, all expansion problems are conviniently solved by %D the primitive \type{\protected}. To put that another way: %D %D It's not a bug in this module if it does not appear in \ETEX! \long\def\dostartpublication[#1]#2\stoppublication% {\increment\bibcounter \bgroup \bgroup\honorunexpanded \doifassignmentelse{#1}% {\egroup\getparameters[\??pb][k=,t=article,n=,s=,a=,y=,o=,#1]}% {\egroup\getparameters[\??pb][k=#1,t=article,n=,s=,a=,y=,o=]}% \toks0={\ignorespaces #2}% \@EA\toks\@EA2\@EA{\@@pba}% \@EA\toks\@EA4\@EA{\@@pbs}% \setxvalue{pbd-\@@pbk}% {{\the\toks2}% \@@pba (author) {\@@pby}% {\the\toks4}% \@@pbs (short) {\@@pbn}% {\@@pbt}% {\the\toks0}% (data) {\@@pbo}}% doi \xdef\allrefs{\allrefs,\@@pbk}% \egroup} % intialization of the order-list: \let\allrefs\empty % how to get stuff from a pbd-*** macro: \def\restorebibdata#1% {\def\@@pbk{#1}% \@EA\dorestorebibdata\csname pbd-#1\endcsname} \def\dorestorebibdata#1% {\@EA\dodorestorebibdata#1{}{}{}{}{}{}{}\relax} \def\dodorestorebibdata#1#2#3#4#5#6#7#8\relax% {\def\@@pba{#1}% \def\@@pby{#2}% \def\@@pbs{#3}% \def\@@pbn{#4}% \def\@@pbt{#5}% \def\@@pbd{#6}% \def\@@pbo{#7}} %D The \writeutility trick is dodgy at best, but it is needed %D to make sure that \placepublications\stoptext works as %D advertised. (without the \immediate, there *has* to be at %D least one page break between \placepublications and \stoptext) %D \def\preinitializepubslist {\let\bibcounter\!!zerocount \ifsortbycite \processcommacommand[\publist]\sortwritepublist \glet\publist\empty \iftypesetall \processcommacommand[\allrefs]\writepublist \fi \else \iftypesetall \processcommacommand[\allrefs]\writepublist \else \processcommacommand[\allrefs]\writereferredpublist \fi \fi} \def\initializepubslist {\edef\@@pbnumbering{\@@pbnumbering}% \ifautohang \ifx\@@pbnumbering\v!short \setbox\scratchbox\hbox{\@@pbnumbercommand{\csname @@pvdata\c!samplesize\endcsname}}% \else\iftypesetall \setbox\scratchbox\hbox{\@@pbnumbercommand{\csname @@pvdata\c!totalnumber\endcsname}}% \else \setbox\scratchbox\hbox{\@@pbnumbercommand{\numreferred}}% \fi\fi \edef\samplewidth{\the\wd\scratchbox}% \setuplist[pubs][\c!width=\samplewidth,\c!distance=0pt]% \def\@@pblimitednumber##1{\hbox to \samplewidth{\@@pbnumbercommand{##1}}}% \else \def\@@pblimitednumber##1{\hbox{\@@pbnumbercommand{##1}}}% \fi \ifx\@@pbnumbering\v!no \setuplist[pubs][\c!numbercommand=,\c!textcommand=\outdented] \else \setuplist[pubs][\c!numbercommand=\@@pblimitednumber,\c!textcommand=] \fi \forgetall % bugfix 2005/03/18 } \def\outdented#1% move to supp-box ? {\hskip -\hangindent \strut#1\strut} %D The full list of publications \def\completepublications {\dosingleempty\docompletepublications} \def\docompletepublications[#1]% {\preinitializepubslist \ifcase\bibcounter\else % HERE it said "\or" instead of "\else" \initializepubslist \let\bibcounter\!!zerocount \completelist[pubs][\c!criterium=all,#1]% \fi} %D And the portion with the entries only. \def\placepublications {\dosingleempty\doplacepublications} \def\doplacepublications[#1]% {\preinitializepubslist \ifcase\bibcounter\else % HERE it said "\or" instead of "\else" \initializepubslist \let\bibcounter\!!zerocount \placelist[pubs][\c!criterium=\v!all,#1]% \fi} \def\dowritebiblist#1#2% {\restorebibdata{#2}% \edef\pbnumbercommand{\@@pbinumbercommand{#1}}% \@EA\dodowritebiblist\@EA{\pbnumbercommand}{\typesetapublication{#2}}} \def\dodowritebiblist {\writetolist[pubs]} \def\writepublist#1% {\doifnotempty{#1} {\increment\bibcounter \@EA\dowritebiblist\@EA{\bibcounter}{#1}}} \def\writereferredpublist#1% {\doifnotempty{#1} {\doifreferredelse{#1} {\increment\bibcounter \@EA\dowritebiblist\@EA{\bibcounter}{#1}}{}}} \def\sortwritepublist#1% {\doifnotempty{#1} {\removefromcommalist{#1}\allrefs \increment\bibcounter \@EA\dowritebiblist\@EA{\bibcounter}{#1}}} %D \subonderwerp{What's in a publication} %D \def\typesetapublication {\doglobal\increment\bibcounter \dotypesetapublication} \def\dotypesetapublication#1% {\bgroup \def\@@currentalternative{data}% \restorebibdata{#1}% \processcommacommand[\bibcommandlist,crossref]\clearbibitem \processcommalist [artauthor,author,editor]\clearbibitemtwo \processcommacommand[\bibcommandlist]\bibitemdefs \processcommalist [artauthor,author,editor,crossref]\bibitemdefs \expanded{\reference[\@@pbk]{\bibcounter}}% \@@pbd % execute data \bibalternative{\@@pbt}% do typesetting \egroup} %D An afterthought \def\maybeyear#1{} %D \onderwerp{Citations} %D \macros{cite,bibref} %D %D The indirection with \type{\dobibref} allows \LATEX\ style %D \type{\cite} commands with a braced argument (these might appear %D in included data from the \type{.bib} file). \def\cite {\doifnextcharelse{[} {\dodoubleempty\docite} {\dobibref}} \def\dobibref#1% {\docite[#1]} \def\docite#1[#2]#3[#4]% {\ifsecondargument \def\@@currentalternative{#2}% \expanded{\processaction[\csname @@pv#2compress\endcsname]} [ \v!yes=>\bibcitecompresstrue, \v!no=>\bibcitecompressfalse, \s!default=>\bibcitecompresstrue, \s!unknown=>\bibcitecompresstrue]% \getvalue{bib#2ref}[#4]% \else \expanded{\processaction[\csname @@pv\@@citedefault compress\endcsname]} [ \v!yes=>\bibcitecompresstrue, \v!no=>\bibcitecompressfalse, \s!default=>\bibcitecompresstrue, \s!unknown=>\bibcitecompresstrue]% \edef\@@currentalternative{\@@citedefault}% \getvalue{bib\@@citedefault ref}[#2]% \fi} \def\setupcite#1[#2]#3[#4]% {\def\getciteargs##1{\getparameters[\??pv##1][#4]}% \processcommalist[#2]\dosetupcite} \def\dosetupcite#1% {\getciteargs{#1}} %D \macros{numreferred,doifreferredelse,addthisref,publist} %D %D The interesting command here is \type{\addthisref}, which maintains %D the global list of references. %D %D \type{\numreferred} is needed to do automatic calculations on %D the label width, and \type{\doifreferredelse} will be used %D to implement \type{criterium=cite}. \newcounter\numreferred \long\def\doifreferredelse#1{\doifdefinedelse{pbr-#1}} \def\addthisref#1% {\doifundefined{pbr-#1} {\setgvalue{pbr-#1}{a}% \doglobal\increment\numreferred \appended\gdef\publist{,#1}}} \let\publist\empty %D \macros{doifbibreferencefoundelse} %D %D Some macros to fetch the information provided by %D \type{\startpublication}. \def\doifbibreferencefoundelse#1#2#3% {\doifdefinedelse{pbd-#1} {\restorebibdata{#1}#2} {\showmessage\m!bib{5}{#1 is unknown}#3}} %D \macros{ixbibauthoryear,thebibauthors,thebibyears} %D %D If compression of \type{\cite}'s argument expansion is on, %D the macros that deal with authors and years call this internal %D command to do the actual typesetting. %D %D Two entries with same author but with different years may %D be condensed into ``Author (year1,year2)''. This is about the %D only optimization that makes sense for the (author,year) %D style of citations (years within one author have to be unique %D anyway so no need to test for that, and ``Author1, Author2 (year)'' %D creates more confusion than it does good). %D %D In the code below, %D the macro \type{\thebibauthors} holds the names of the alternative %D author info fields for the current list. This is a commalist, %D and \type{\thebibyears} holds the (collection of) year(s) that go with %D this author (possibly as a nested commalist). %D %D There had better be an author for all cases, but there %D does not have to be year info always. \type{\thebibyears} is %D pre-initialized because this makes the insertion macros simpler. %D %D In `normal' \TeX, of course there are expansion problems again. \def\gobble#1{\def#1##1{##1}} \def\sanitizeaccents{\processcommalist[\',\`,\",\.,\c,\d,\~,\=]\gobble} \def\ixbibauthoryear#1#2#3#4% {\bgroup \sanitizeaccents \gdef\ixlastcommand {#4}% \gdef\ixsecondcommand{#3}% \gdef\ixfirstcommand {#2}% \glet\thebibauthors \empty \glet\thebibyears \empty \glet\theauthorssize \empty \getcommalistsize[#1]% \ifbibcitecompress \dorecurse\commalistsize{\xdef\thebibyears{\thebibyears,}}% \processcommalist[#1]\docompressbibauthoryear \else \processcommalist[#1]\donormalbibauthoryear \fi \getcommacommandsize[\thebibauthors]% \xdef\theauthorssize{\commalistsize}% \egroup \dobibauthoryear} %D \macros{dodobibauthoryear} %D %D This macro only has to make sure that the lists %D \type{\thebibauthors} and \type{\thebibyears} are printed. \def\dobibauthoryear {\scratchcounter\zerocount \getcommacommandsize[\thebibauthors]% \@EA\processcommalist\@EA[\thebibauthors]\dodobibauthoryear} \def\dodobibauthoryear#1% {\advance\scratchcounter\plusone \edef\wantednumber{\the\scratchcounter}% \getfromcommacommand[\thebibyears][\wantednumber]% \def\AU{#1}% brr \@EA\def\@EA\YR\@EA{\commalistelement}% \ifnum\scratchcounter=\plusone \ixfirstcommand \else\ifnum \scratchcounter=\commalistsize\relax \ixlastcommand \else \ixsecondcommand \fi\fi} %D \macros{donormalbibauthoryear} %D %D Now we get to the macros that fill the two lists. %D The `simple' one really is quite simple. \def\donormalbibauthoryear#1% {\addthisref{#1}% \xdef\myauthor{Xxxxxxxxxx}% \xdef\myyear{0000}% \doifbibreferencefoundelse{#1} {\@EA\gdef\@EA\myauthor\@EA{\@@pba}% \@EA\gdef\@EA\myyear \@EA{\@@pby}} {}% \@EA\doglobal\@EA\addtocommalist\@EA{\myauthor}\thebibauthors \@EA\doglobal\@EA\addtocommalist\@EA{\myyear }\thebibyears} %D \macros{docompressbibauthoryear} %D %D So much for the easy parts. Nothing at all will be done if %D the reference is not found or the reference does not contain %D author data. No questions marks o.s.s. (to be fixed later) \def\docompressbibauthoryear#1% {\addthisref{#1}% \xdef\myauthor{Xxxxxxxxxx}% \xdef\myyear {0000}% \doifbibreferencefoundelse{#1} {\@EA\gdef\@EA\myauthor\@EA{\@@pba}% \@EA\gdef\@EA\myyear \@EA{\@@pby}} {}% \ifx\myauthor\empty\else \checkifmyauthoralreadyexists \findmatchingyear \fi} %D two temporary counters. One of these two can possibly be replaced %D by \type{\scratchcounter}. \newcount\bibitemcounter \newcount\bibitemwanted %D The first portion is simple enough: if this is the very first author %D it is quite straightforward to add it. \type{\bibitemcounter} and %D \type{\bibitemwanted} are needed later to insert the year %D information in the correct item of \type{\thebibyears} \def\checkifmyauthoralreadyexists {\doifemptyelsevalue{thebibauthors} {\global\bibitemcounter\plusone \global\bibitemwanted \plusone \@EA\gdef\@EA\thebibauthors\@EA{\myauthor}} % hh: one level {\getcommacommandsize[\thebibauthors]% \global\bibitemwanted\zerocount \global\bibitemcounter\commalistsize \processcommacommand[\thebibauthors]\docomparemyauthor}} %D The outer \type{\ifnum} accomplishes the addition of %D a new author to \type{\thebibauthors}. The messing about with %D the two counters is again to make sure that \type{\thebibyears} %D will be updated correctly.If the author {\it was} found, %D the counters will stay at their present values and everything %D will be setup properly to insert the year info. \def\docomparemyauthor#1% {\global\advance\bibitemwanted \plusone \def\mytempc{#1}% \ifnum\bibitemwanted = \commalistsize\relax \ifx\mytempc\myauthor \else \global\advance\bibitemwanted \plusone \global\bibitemcounter\bibitemwanted\relax \@EA\doglobal\@EA\addtocommalist\@EA{\myauthor}\thebibauthors \quitcommalist \fi \else \ifx\mytempc\myauthor \quitcommalist \fi \fi} %D This macro should be clear now. \def\findmatchingyear {\edef\wantednumber{\the\bibitemwanted}% \getfromcommacommand[\thebibyears][\wantednumber]% \ifx\commalistelement\empty \edef\myyear{{\myyear}}% \else \edef\myyear{{\commalistelement, \myyear}}% \fi \edef\newcommalistelement{\myyear}% \doglobal\replaceincommalist \thebibyears \wantednumber} %D \macros{bibauthoryearref,bibauthoryearsref,bibauthorref,bibyearref} %D %D Now that all the hard work has been done, these are simple. %D \type{\ixbibauthoryearref} stores the data in the macros %D \type{\AU} and \type{\YR}. \def\bibauthoryearref[#1]% {\ixbibauthoryear{#1}% {{\AU}\bibalternative\c!inbetween \bibalternative\v!left{\YR}\bibalternative\v!right} {\bibalternative\c!pubsep{\AU}\bibalternative\c!inbetween \bibalternative\v!left {\YR}\bibalternative\v!right} {\bibalternative\c!lastpubsep{\AU}\bibalternative\c!inbetween \bibalternative\v!left {\YR}\bibalternative\v!right}} \def\bibauthoryearsref[#1]% {\bibalternative\v!left \ixbibauthoryear{#1} {{\AU}\bibalternative\c!inbetween{\YR}} {\bibalternative\c!pubsep {\AU}\bibalternative\c!inbetween{\YR}} {\bibalternative\c!lastpubsep{\AU}\bibalternative\c!inbetween{\YR}}% \bibalternative\v!right} \def\bibauthorref[#1]% {\bibalternative\v!left \ixbibauthoryear{#1}% {{\AU}} {\bibalternative\c!pubsep {\AU}} {\bibalternative\c!lastpubsep{\AU}}% \bibalternative\v!right} \def\bibyearref[#1]% {\bibalternative\v!left \ixbibauthoryear{#1}% {{\YR}} {\bibalternative\c!pubsep {\YR}} {\bibalternative\c!lastpubsep{\YR}}% \bibalternative\v!right} %D ML problems: %D \macros{bibshortref,bibkeyref,bibpageref,bibtyperef,bibnumberref} %D %D There is hardly any point in trying to compress these. The only %D thing that needs to be done is making sure that %D the separations are inserted correctly. And that is %D what \type{\refsep} does. \newif\iffirstref \def\refsep{\iffirstref\firstreffalse\else\bibalternative\c!pubsep\fi} \def\bibshortref[#1]% {\bibalternative\v!left \firstreftrue\processcommalist[#1]\dobibshort \bibalternative\v!right} \def\dobibshort#1% {\addthisref{#1}\refsep \doifbibreferencefoundelse{#1}{\@@pbs}{??}} \def\bibnumberref[#1]% {\bibalternative\v!left \firstreftrue\processcommalist[#1]\dobibnumbered \bibalternative\v!right} \def\dobibnumbered#1% {\addthisref{#1}\refsep \doifbibreferencefoundelse{#1}{\@@pbn}{??}} \def\bibkeyref[#1]% {\bibalternative\v!left \firstreftrue\processcommalist[#1]\dobibkeyref \bibalternative\v!right} \def\dobibkeyref#1% {\addthisref{#1}\refsep#1} \def\bibdoiref[#1]% {\bibalternative\v!left \firstreftrue\processcommalist[#1]\dobibdoiref \bibalternative\v!right} \def\dobibdoiref#1% {\addthisref{#1}\refsep#1} \def\bibtyperef[#1]% {\bibalternative\v!left \firstreftrue\processcommalist[#1]\dobibtyperef \bibalternative\v!right} \def\dobibtyperef#1% {\addthisref{#1}\refsep \doifbibreferencefoundelse{#1}{\@@pbt}{??}} \def\bibpageref[#1]% {\bibalternative\v!left \firstreftrue\processcommalist[#1]\dobibpageref \bibalternative\v!right} \def\dobibpageref#1% {\addthisref{#1}\refsep\at[#1]} \def\bibdataref[#1]% {\bibalternative\v!left \firstreftrue\processcommalist[#1]\dobibdata \bibalternative\v!right} \def\dobibdata#1% {\addthisref{#1}\refsep \doifbibreferencefoundelse{#1}{\dotypesetapublication{#1}}{??}} %D \macros{bibnumref} %D %D It makes sense to try and compress the argument list of %D \type{\bibnumref}. There are two things involved: the actual %D compression, and a sort routine. The idea is to store the %D found values in a new commalist called \type{\therefs}. %D But that is not too straight-forward, because \type{\in} is %D not expandable, %D so that the macro \type{\expandrefs} is needed. \def\expandrefs#1% {\doifreferencefoundelse{#1} {\@EA\doglobal\@EA\addtocommalist\@EA{\reftypet}\therefs } {\showmessage\m!bib{5}{#1 unknown}% \doglobal\addtocommalist{0}\therefs}} %D But at least the actual sorting code is simple (note that sorting %D a list with exactly one entry fails to return anything, which %D is why the \type{\ifx} is needed). \ifx\compresscommacommandnrs\undefined \usemodule[list] \let\compresscommacommandnrs\compresscommacommand \fi \def\bibnumref[#1]% {\bibalternative\v!left \penalty\!!tenthousand \processcommalist[#1]\addthisref \firstreftrue \ifbibcitecompress \glet\therefs\empty \processcommalist[#1]\expandrefs \sortcommacommand[\therefs]\donumericcompare \ifx\empty\sortedcommalist\else \let\therefs\sortedcommalist \fi \compresscommacommandnrs[\therefs]% % \message{\meaning\therefs, \meaning\compressedlist}% \processcommacommand[\compressedlist]\verysimplebibnumref \else \processcommalist[#1]\dosimplebibnumref \fi \bibalternative\v!right} %D Here is the simple case first: \def\dosimplebibnumref #1{\refsep\in[#1]} \def\verysimplebibnumref#1{\doverysimplebibnumref#1} \def\doverysimplebibnumref#1#2% {\refsep \ifcase#1\relax ??\else \def\tempa{#2}\ifx\empty\tempa#1\else#1\bibalternative\c!inbetween#2\fi \fi} %D And some defaults are loaded from bibl-apa: % hh: shouldn't those bibl files be made international ? \setuppublications [\c!alternative=apa] %D \completepublications \protect \endinput