% \iffalse meta-comments % msg.dtx original file name. This is a 8bits file. % % Copyright (C) 2004 LPPL - Bernard Gaulle. % % This file may be distributed and/or modified under the conditions of % the LaTeX Project Public License as of http://www.latex-project.org/lppl.txt % % This file has the LPPL maintenance status "maintained". % The current maintainer is Bernard.Gaulle at idris.fr % \fi % \CheckSum{1333} % \iffalse % \begin{macrocode} %<*README> %% To unpack this package: latex msg.ins %% To prepare for TeX Live: make TL %% %% HERE IS THE MSG PACKAGE FOR LaTeX %% %% A LaTeX package to localize any package or document class. %% %% A LaTeX package able to issue messages in the language provided as option %% of \documentclass or in use in the document (\languagename). All messages %% are identified with a unique "id" and stored in a MessagesFile whose name %% is related to the package and optionnaly to the language. %% %% MessagesFile, name: []_-msg.tex %% contents: \msg{}{} % defines the message "id". %% \msg*{}{} % star form for msg emphasis. %% \msg{*}{} % bad "id" default message. %% Messages can have 3 more parts defined asis: %% \msg{}{}[ % defines the msg first part. %% \msgparti{} % defines the msg second part. %% \msgpartii{} % defines the msg third part. %% \msgpartiii{}] % defines the msg fourth part. %% Any message part can include a |#1| parameter provided from any %% of the macros below. %% Error messages have just a help more part as follows: %% \msg{}{}[ % defines the msg first part. %% \help{}] % defines the help part. %% All messages should be fully expandable. %% Custolization: %% \msgheader{} %% \msgtrailer{} %% \msgencoding{}% as for inputenc. %% Check "msg-msg.tex" file for msg's own messages file. %% %% Document usage: \documentclass[any_option]{any_class} %% call: \usepackage[options,language]{msg} %% %% to issue the message "id": \issuemsg{}()[#1] %% One can use any message macro (defaultly \typeout) with: %% \issuemsg[msg_macro]{}()[#1] %% Multi-parts message can't be issued through \issuemsg. %% One can specify the macro name to issue message as an option %% of \usepackage: \message, \wlog, \typeout, \kbtypyeout or %% \ClassWarning, \ClassError, \PackageWarning, \PackageError, ... %% %% to retrieve the message "id" in \themsg (without typesetting): %% \retrievemsg{}()[#1] %% Multi-parts message will have defined also \themsgi, %% \themsgii and \themsgiii. %% to get the message "id": \getmsg{}()[#1] %% %% Usually, the requested message "id" is retrieved from %% []_-msg.tex but if there is no active language %% or if file don't exist then message is searched in the %% -msg.tex file. %% %% For testing a messages file, you can code: %% \issueallmsg[msg_macro]() %% and all messages from the file will be retrieved and issued. %% %% For tracing all accessed files you should load the "msg" package with %% the option: tracefiles. %% %% In case of trouble you can ask the "msg" package not to load %% any message file, just load the "msg" package with the %% option: noop, and then you just obtain a message containing %% the "msgid". %% %% Please look at the documentations for more details. %% % % \end{macrocode} % \fi % \catcode`\<=\active\def<{$\langle$} % \catcode`\>=\active\def>{$\rangle$} % \def\msgname{``\textsf{msg}''} % \title{\vspace*{-1cm}The \LaTeXe\ \msgname\ package\\ % for package localization\thanks{This file has version % \fileversion\ last revised \filedate}\\[0.25\baselineskip] % \ifguide\textit{Package writer's guide} % \else\textit{Comprehensive documentation} % \fi} % \author{Bernard \textsc{Gaulle}} % \date{As of \filedate % \vfill{\small\tableofcontents}} % \maketitle % % \section{Introduction} % % Since a \LaTeX\ package issues various messages, mostly in English (but, % unfortunately, often in an English-like language), it is usefull % to provide a feature to localize any \LaTeXe\ package or document class. % The \msgname\ package is designed for that. % Messages are in dedicated files and retrieved when needed.\\ % % Packages writers (as well as document class writers) just have to create % their native messages file and ask for any message when needed. % % \ifguide\else % \section{The documentation driver} % % This code will generate the documentation. Since it is the first piece of % code in the file, the documentation can be obtained by simply processing % this file with \LaTeXe. % % We just load the \msgname\ package for self testing purposes (which needs % we keep track of the |doc|'s |\MakePercent| macros later used). % \fi % \begin{macrocode} %<*driver> \documentclass[10pt]{ltxdoc} \makeatletter \let\msg@MPC\MakePercentComment \let\msg@MPI\MakePercentIgnore \makeatother \usepackage[T1]{fontenc} \usepackage{lmodern}% You can remove it if you don't have that font. \usepackage{makeidx} \usepackage[tracefiles]{msg} % \usepackage{msg}% should also be tested without "tracefiles" \begin{document} \let\hard\relax\let\endhard\relax\let\ifguide\iffalse \DocInput{msg.dtx} \end{document} % % \end{macrocode} % % \ifguide\else % A package writer's guide can also be typeset using the file % |msgguide.tex|. % \fi % % \ifguide\else % \section{Initialization} % % Check if the msg package is already loaded and if yes end input. % Set the ``catcode'' for |@| if not already done. % Assume defaultly that the output macro (|\issuemsgio|) % will be |\typeout| if not already initiated. Force the \texttt{inputenc} % package to be loaded, if not already done and even from a Babel option % since it could issue messages via our \msgname\ package. % Check also if the english ``msg'' file \texttt{msg-msg.tex} is not installed % to detect the original bug of TeXLive 2005 and then stop typesetting. % \fi % % \begin{macrocode} %<*code> \iffalse checksum part %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% checksum = "32817 1583 6882 65979" %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \fi \def\fileversion{V0.51}\def\filedate{2019/01/01}% \ifx\issuemsg\undefined\else\expandafter\endinput\fi% \ifnum\catcode`\@=11\else\expandafter\catcode`\@=11\fi% \ifx\kbencoding\undefined% If we don't have any keyboard reencoding \ifx\LdfInit\@undefined% we need at least inputenc package. \RequirePackage{inputenc}% Usually, load that package. \else% But with Babel, dont use \usepackage or such, \let\@msg@tempa\@currname% Save current package name. \xdef\@currname{inputenc}% set package req. \@@input inputenc.sty% and input it now. \makeatletter% \let\@currname\@msg@tempa% Reset original package name. \fi% \let\@previeg\empty% We have no encoding at this time. \fi% \IfFileExists{msg-msg.tex}{}{% \message{msg: ERROR, file msg-msg.tex is missing}\stop% }% % \end{macrocode} % \begin{macro}{\issuemsgio} % \begin{macrocode} \ifx\issuemsgio\undefined\let\issuemsgio\typeout\fi% % \end{macrocode}\label{msgio} % \end{macro} % % \ifguide\else % Verify that |\languagename| which is % set by \texttt{babel} or \texttt{mlp} or \texttt{frenchpro} % or \texttt{frenchle} or \ldots % is not a virtual language such as % |dummy| or |nohyphenation| and then keep it as % the \msgname\ package's language name. % \fi % % \begin{macrocode} \def\@msg@tempa{dummy}% \def\@msg@tempb{nohyphenation}% \def\@msg@tempc{english}% Default language for msg package. \ifx\languagename\@msg@tempa\else% \ifx\languagename\@msg@tempb\else% \ifx\languagename\@msg@tempc\let\msg@languagename\undefined\else \ifx\languagename\undefined\let\msg@languagename\undefined% \else\edef\msg@languagename{\languagename}% Set it for now. \fi% \fi% \fi% \fi% % \end{macrocode} % \ifguide\else % \begin{macro}{\packagewarningheader}|#1| % This code is designed to localize text of macro |\PackageWarning| which % we, now, redefine. % % \begin{macrocode} \def\packagewarningheader#1{Package #1 Warning: }% % \renewcommand{\PackageWarning}[2]{\GenericWarning{(#1)% \@spaces\@spaces\@spaces\@spaces}% {\packagewarningheader{#1}#2}% } % \end{macrocode} % \end{macro}\label{pw} % % Few other internal \LaTeX\ macros might be localized here... but preferably % within the kernel. % \fi % % \begin{macrocode} \edef\@msg@code@ast{\the\catcode`\*}% Save the current catcode of ``*''. % \end{macrocode} % % \section{Macros to be used in a \LaTeX\ package} % % Basically, three macro commands can be coded for package localization:\\ % |\issuemsg|, |\getmsg| and |\retrievemsg|. % Another macro, |\issuemsgx| is given for specific cases, we will see % that later, page \pageref{encodings}. % % \subsection*{Output a message} % % Here is the main macro which will issue a message ``id'' via the % command |\issuemsgio| defaultly set to |\typeout| % \ifguide.\else(cf page~\pageref{msgio}).\fi % \begin{macro}{\issuemsg}|[#1]#2(#3)[#4]| % \begin{macro}{\issuemsgx}|[#1]#2(#3)[#4]| % \begin{macrocode} \def\issuemsg{\@ifnextchar[{\i@suemsg}{\i@suemsg[\issuemsgio]}%] }% \def\issuemsgx{\@ifnextchar[{\i@suemsgx}{\i@suemsgx[\issuemsgio]}%] }% % \end{macrocode} % \end{macro} % \end{macro} % One can provide another command to issue the message % by the way of the first optional argument. The second argument is the % message ``id''; the third is the name of the package (or document % class\footnote{Each time we are talking about a \LaTeX\ package, please % consider it applies also to any \LaTeX\ document class.}) % which provides that message through a % message file whose name is |[language_]package-msg.tex|. Lastly an optional % parameter can be set to ``|#1|\footnote{You can put here % any replacement text instead of this \texttt{\#1} parameter. Be careful, % this parameter or replacement text will be, usually, expanded; so % protect any string which should not with a \texttt{\textbackslash string} % prefix.}'' to forward an argument % directly inside the message content. I thought the syntax would be too % much complicated to offer much more parameters through that mean. % We will see later that the message can also be split in four parts, % allowing anyone to display the message differently but not as % |\issuemsg| does. % % \begin{center} % \fbox{{\texttt{\textbackslash issuemsg[<\emph{message\_macro}>]\{<\emph{id}>\}(<\emph{package}>)[\#1]}}} % \end{center} % % The message macro could be the usual |\typeout| or any other output macro % with one argument such as |\message| or |\wlog|. % You can also code a macro with two arguments, such as |\ClassWarning|, % |\ClassWarningNoLine|, |\PackageWarning|, |\PackageWarningNoLine|, % |\ClassInfo| or |\PackageInfo| which have just a name as first argument, % like this: % % \begin{center} % \fbox{{\texttt{\textbackslash issuemsg[<\emph{message\_macro\{arg1\}}>]\{<\emph{id}>\}(<\emph{package}>)[\#1]}}} % \end{center} % That way the first argument is not localized (usually this is a class or % package name) and the second argument is provided by the message file % entry and so localized. % % You can also use special error macros with 3 arguments as explained below. % % \subsection*{Willing to issue a % {\mdseries\texttt{\textbackslash PackageError}}?} % \label{willingPE} % % The \msgname\ package is designed for basic macro messages which have % just only one text argument to localize. % The |\PackageError| is one exception; it has % 3 arguments: the first one (name of package in error: % |<|\texttt{\emph{package1}}|>|) which is given as the following: % % \begin{center} % \fbox{{\texttt{\textbackslash issuemsg[\textbackslash PackageError\{<\emph{package1}>\}]\{<\emph{id}>\}(<\emph{package2}>)[\#1]}}} % \end{center} % % \noindent the other two arguments will be retrieved from the message file % of \texttt{<\emph{package2}>} and localized. % % The same coding can be used for |\ClassError|: % % \begin{center} % \fbox{{\texttt{\textbackslash issuemsg[\textbackslash ClassError\{<\emph{class1}>\}]\{<\emph{id}>\}(<\emph{class2}>)[\#1]}}} % \end{center} % % \subsection*{Examples \& tests\\ % (using the message files listed page \pageref{msgfiles})} % |\issuemsg1(msg)| will give at the console: \\ % \centerline{\tt\getmsg1(msg)} but % |\issuemsg01(msg)| will give: \retrievemsg01(msg){\tt\themsg}. % % While defining |\def\test#1{`\issuemsg4(msg)[#1]'}| the following call % |\emph{\test{SPECIAL}}| will print: \def\test#1{`\getmsg4(msg)[#1]'}\\ % \centerline{\emph{\test{SPECIAL}}} showing that the argument % was inserted inside the message at the exact area, replacing |#1|. % % In a French document, the same codes will issue:\\ % \bgroup\makeatletter\@msgINfrench\def\msg@languagename{french} % \centerline{\tt\getmsg1(msg)} % \centerline{\retrievemsg01(msg){\tt\themsg}} % \centerline{\emph{\test{SPECIAL}}} % \egroup % % \begin{macrocode} \let\@msgalspace\space% \def\@msgalign#1{\ifx\empty#1\else\expandafter\@msgalign@% \expandafter#1\fi}% \def\@msgalign@#1{\ifx\void#1\else\expandafter\@msgalign@@% \expandafter#1\fi}% \def\@msgalign@@#1{\ifx\protect#1\expandafter\@msgalign@@@% \else\expandafter\@msgalign@@@@% \fi}% \def\@msgalign@@@{\@msgalign}% \def\@msgalign@@@@{\@msgalspace\@msgalign}% \let\msg@cmd\relax% \def\i@suemsg{\let\msg@cmd\issuemsg\i@suemsgx}% \def\i@suemsgx[#1]#2(#3){\@ifnextchar[{\i@@uemsg[#1]#2(#3)}%] {\i@@uemsg[#1]#2(#3)[]}% }% \let\if@msg@pkg@error\iffalse% Defaultly, not an error macro message. \def\i@@uemsg[#1]#2(#3)[#4]{% \def\@argmsg{#4}% \def\@msg@iocmd{#1}% \def\@msg@txt{% \themsg\themsgi\themsgii\themsgiii% }% \let\@msg@MBori\MessageBreak% \ifx\MessageBreak\relax% \def\MessageBreak{^^J\expandafter\@msgalign\msg@header\void}% \fi% % \end{macrocode} % % \ifguide\else % Here, we check for error macros and, if any, set the flag for % further processing. % \fi % % \begin{macrocode} \let\@msg@txt@\empty% \def\@msg@tempb##1##2/{\let\@msg@tempb=##1}% \def\@msg@tempa{\let\if@msg@pkg@error\iftrue}% \@msg@tempb#1/% \PackageError is a special case with \ifx\@msg@tempb\PackageError% package name and msg+help. \@msg@tempa% Keep it in mind for \@msgparts. \fi% % \end{macrocode} % % \ifguide\else % Now we test if the output macro name provided is well defined ; if not % we retrieve our own message \#1 in place of requested one, otherwise % we call the |\retrievemsg| macro and output the message text parts. % \fi % % \begin{macrocode} \ifx\@msg@tempb\ClassError% The same for \ClassError. \@msg@tempa% \fi% \ifx\undefined#1\retrievemsg2(msg)% \PackageWarning{msg}\@msg@txt% \else\retrievemsg#2(#3)[#4]% \ifx\kbencoding\undefined% Expand text now if \edef\@msg@txt{\@msg@txt}% output encoding is \edef\@msg@txt@{\@msg@txt@}% not available. \fi% \@relaxORgobble\@msg@iocmd{\@msg@txt}{\@msg@txt@}% %%% \csname @originalkbe\endcsname% Get back encoding if necessary. \fi% \let\MessageBreak\@msg@MBori% }% % \end{macrocode} % % \subsection*{Get a message for typesetting} % % Sometimes we only want to get the message and typeset it. The syntax is % the same as |\issuemsg| except there is no first optional argument for % providing the macro name to issue the message since it is not issued at all. % % \begin{center} % \fbox{{\texttt{\textbackslash getmsg\{<\emph{id}>\}(<\emph{package}>)[\#1]}}} % \end{center} % \subsection*{Examples \& tests} % |`\textsl{\getmsg1(msg)}'| will insert at this point % for typesetting the message: `\textsl{\getmsg1(msg)}'; % nothing is issued at the console nor in the % log, except if the |<|\emph{id}|>| is not found in the message file. % % In a French document, the same code will issue: % % \bgroup\makeatletter\def\msg@languagename{french} % \centerline{`\textsl{\getmsg1(msg)}'} % \egroup % % \ifguide\else % Here is the very simple code for |\getmsg|; just a |\retrievemsg| and % the expansion of the message when correctly retrieved. % \fi % % \begin{macro}{\getmsg}|#1(#2)[#3]| % \begin{macrocode} \def\getmsg#1(#2){\@ifnextchar[{\g@tmsg#1(#2)}{\g@tmsg#1(#2)[]}%] }% \def\g@tmsg#1(#2)[#3]{\retrievemsg{#1}(#2)[#3]\@relaxORgobble% \themsg}% % \end{macrocode} % \end{macro} % % \subsection*{The message file input routine}\label{readingprocess} % % To avoid having superfluous file names listed in the \texttt{log} % each time we request a message from a file, defaultly we read the % file with the \TeX\ |\read| command\ifguide.\else, as the following. % This code will not be used when the option |tracefiles| is given (in % which case we will input the message file with an usual |\input| macro). % \fi % \label{readcode} % % \begin{macrocode} \newif\if@msg@more% \def\@msglineparse#1#2\void{\def\@msg@tempa{\msg}% \def\@msg@tempb{#1}% \ifx\@msg@tempa\@msg@tempb% \@msg@tempf% Execute the previous line. \def\@msg@tempf{}% Start a new one. \if@msg@more% Continue line feed. \def\@msg@tempf{\protect#1#2}% \fi% \else% \let\msgheaderOLD\msgheader% \let\msgtrailerOLD\msgtrailer% \let\msgencodingOLD\msgencoding% \let\spaceOLD\space% \let\UTFviii@two@octetsOLD\UTFviii@two@octets% \let\UTFviii@three@octetsOLD\UTFviii@three@octets% \let\UTFviii@four@octetsOLD\UTFviii@four@octets% \let\UTFviii@two@octets\string% If utf8 was loaded then \let\UTFviii@three@octets\string% nullify it until \let\UTFviii@four@octets\string% necessary. \def\msgheader{\protect\msgheader}% \def\msgtrailer{\protect\msgtrailer}% \def\msgencoding{\protect\msgencoding}% \def\space{\noexpand\space}% \def\help{\protect\helpi}% \protected@edef\@msg@tempf{\@msg@tempf\@msgline}% \let\UTFviii@two@octets\UTFviii@two@octetsOLD% \let\UTFviii@three@octets\UTFviii@three@octetsOLD% \let\UTFviii@four@octets\UTFviii@four@octetsOLD% \let\space\spaceOLD% \let\msgheader\msgheaderOLD% \let\msgtrailer\msgtrailerOLD% \let\msgencoding\msgencodingOLD% \let\spaceOLD\undefined% \let\msgheaderOLD\undefined% \let\msgtrailerOLD\undefined% \let\msgencodingOLD\undefined% \fi% }% % \end{macrocode} % % NOTICE: all messages read until the requested one (included) are expanded % (before parsing) in the following macro. Thus, each (|\msg|) macro call % should contain significant value or |\protect| a macro. The same reason % applies to |\msgheader| and |\msgtrailer| we will discuss later (cf % p~\pageref{msgtrailerdef}). % % \begin{macrocode} \let\endinputORI\endinput% Save \endinput for any use in an alone \msgencoding \newread\@inputmsg% We'll need it at least for the banner message. \def\@@input@msg@filename{% Doing nearly like \@@input\msg@filename \openin\@inputmsg=\msg@filename\@msg@moretrue% \let\msgparti\relax% \let\msgpartii\relax% \let\msgpartiii\relax% \def\@msg@tempf{}% \let\endinputORI\endinput% \let\endinput\undefined% To avoid redef info msg. \DeclareRobustCommand*{\endinput}{\@msg@morefalse% }% \let\reserved@a\@gobble% Clean remaining code. \loop\catcode`\#=\active% \endlinechar=-1% \read\@inputmsg to \@msgline% \endlinechar`\^^M% \catcode`\#=6% \ifx\@msgline\empty\else% \expandafter\@msglineparse\@msgline\void% \fi% \ifeof\@inputmsg\@msg@morefalse\fi% \if@msg@more\repeat% \closein\@inputmsg\@msg@tempf% \catcode`\#=6% \let\endinput\endinputORI% }% \def\@msginput@usual{\let\endinputORI\endinput\@@input\msg@filename}% % \end{macrocode} % % % \subsection*{Just retrieve \texttt{\textbackslash themsg}} % % % One can also want to retrieve the message from the file and save % it in a macro for later use. % In fact, if this is a one-part message it will be saved % in |\themsg|, otherwise this will be the first part message and other parts % will be saved in |\themsgi|, |\themsgii| and |\themsgiii|. % \ifguide\else % This will be achieved via the |\retrievemsg| macro defined as the % following: % \fi % % \begin{macro}{\retrievemsg}|#1(#2)[#3]| % \begin{macrocode} \def\retrievemsg#1(#2){\catcode`\*=\@msg@code@ast% \@ifnextchar[{\r@trievemsg#1(#2)}%] {\r@trievemsg#1(#2)[]}% }% % \end{macrocode} % \end{macro} % \begin{macrocode} \let\msg@empty\empty% \let\if@msgnext\iffalse% Set no request for all messages. % \end{macrocode} % \begin{macro}{\themsg} % \begin{macro}{\themsgi} % \begin{macro}{\themsgii} % \begin{macro}{\themsgiii} % \begin{macro}{\msgid}\end{macro} % \begin{macrocode} \def\r@trievemsg#1(#2)[#3]{\def\@argmsg{#3}% \let\msg@header\empty\let\msg@trailer\empty% \xdef\msgid{#1}% \def\@msg@pkg{#2}% Prevent from empty file: \let\themsg\msg@empty% \if@msgnext\let\help\helpi\fi% \let\themsgi\empty% \let\themsgii\empty% \let\themsgiii\empty% % \end{macrocode} % \end{macro}\end{macro}\end{macro}\end{macro} % \begin{macrocode} \let\@relaxORgobble\relax% \edef\@msg@tempd{\@msg@pkg-msg.tex}% \ifx\msg@languagename\undefined% \ifx\languagename\undefined\else% Get current language. \let\msg@input@lang\languagename% \fi% If no current language, use msg's language. \else\let\msg@input@lang\msg@languagename% \fi% \csname msg@MPC\endcsname% req. when ltxdoc \ifx\msg@input@lang\undefined% \let\msg@filename\@msg@tempd% \else% \edef\@msg@tempc{\msg@input@lang\string_\@msg@tempd}% \IfFileExists\@msg@tempc{\let\msg@filename\@msg@tempc}% {\let\msg@filename\@msg@tempd}% \fi% \edef\msg@inputlineno{the\inputlineno}% \makeatletter% \let\@msg@gobble@space\relax% Case \msgheader in 1st line. \let\reserved@a\@gobble% Avoid runaway. \bgroup\@@input@msg@filename\relax\egroup% \let\msg@cmd\relax% \csname msg@MPI\endcsname% req. when ltxdoc \ifx\themsg\empty% Unusual end of file reached. \def\@msg@tempa{\let\msg@empty\relax% to avoid loop. \r@trievemsg6(msg)[]% }% \expandafter\@msg@tempa% \fi% \ifx\themsg\msg@empty% \PackageError{msg}% {\string\msg{*} not found in \msg@filename}% {please reinstall the msg package}% \fi% \let\if@msg@pkg@error\iffalse% Reset for next msg request. \catcode`\*=\@msg@code@ast% Reset catcode too. }% % \end{macrocode} % % The |\retrievemsg| command is the heart of all macros to obtain the % wanted message. It will input the message file, depending on the % language to use, searching for the message ``id''. If this is a valid % language (i.e. defined in the \texttt{language.dat} % file in use) and the corresponding % language file exists it is inputed otherwise it is the package default % message file which is inputed (which should be usually in English). % In case the message ``id'' is still not found in that file and no % ``|*|'' message ``id'' exists we will try to access message number 6 % of the \msgname\ package. And again, if still not found we terminate % the process with a final package error; this is the only English message % hard coded in the \msgname\ package. Localization might occur but % should be also hard coded; not really usefull since it is not % addressed to the end user but to a package or class writer. % % \begin{center} % \fbox{{\texttt{\textbackslash retrievemsg\{<\emph{id}>\}(<\emph{package}>)[\#1]}}} % \end{center} % \subsection*{Examples \& tests} % \retrievemsg1(msg) % |\retrievemsg1(msg)| will set |\themsg| with the value of % the corresponding message ; nothing is issued at the console % nor in the log, except if the |<|\emph{id}|>| is not found in % the message file. % % \noindent|\show\themsg| will explain: % % \noindent|> \themsg=macro:| % % \noindent|->|\texttt{\themsg} % % \noindent In a French document, the same code will issue: % % \bgroup\makeatletter\def\msg@languagename{french} % \retrievemsg1(msg) % \noindent|> \themsg=macro:| % % \noindent|->|\texttt{\themsg} % \egroup % % In case the message file is empty or do not contain neither the message % ``id'' nor any |\msg{*}| macro then we will obtain: % \bgroup\makeatletter % \catcode`*=\active\let*\relax%^^A for expansion when \read case. % \let\@msg@code@ast=\active%^^A to simulate a missing \msg{*}. % \retrievemsg999(msg) % % \noindent|> \themsg=macro:| % % \noindent|->|\texttt{\themsg} % \egroup % % It may also arrive that we don't find that former message (|#6|) at all % then we will issue the usual \LaTeX\ |\PackageError| macro. % % \section{The message files} % % The default (English) message files should have the name % \texttt{\emph{package}-msg.tex} and localized ones should be % \texttt{\emph{language}\_\emph{package}-msg.tex}. % I would have prefered the file names begin with a dot which is % a hidden file in unix and thus avoid visual pollution inside packages % directories but, unfortunately, writing them with |doctrip| is % generally forbiden due to `|openout_any = p|' in |texmf.cnf| % configuration file. % % These files contain only the messages which could be requested % by the associated \texttt{\emph{package}}. It is important to say now % that when a message is split on multiple lines, each line must end % with "\verb*X %X" to avoid to loose the ending space when any is % required; this is due to the special |\read|ing process shown % \ifguide.\else % page \pageref{readingprocess}. % % \subsection*{About the \TeX\ Directory Structure} % % Notice that a specfic area where to place these files could be % defined in the TDS. % % \bigskip\noindent % WARNING regarding the TDS: currently file names in the TDS should not % exceed 8 characters to be 8.3 file system compliant. % Thus file names used by the \msgname\ package have % a great chance to be not TDS compliant. The files would not be used % also on ISO-9660 CD-ROMs. But, as said Karl Berry: "I rather % doubt TeX Live itself would be usable on an 8.3 filesystem these days". % \bigskip % \fi % % \subsection*{Message files contents} % % A typical file content is the following |msg-msg.tex| file, used by % the \msgname\ package itself: % %\hard % \begin{macrocode} %<*english> % File: msg-msg.tex % Here are the English messages for the \msgname\ package. % % The following line is just for testing purpose: \msgencoding{}\msgheader{}\msgtrailer{} \msg{1}{\filedate\space \fileversion\space package to issue localized % messages, now loaded.}{} \msg{2}{invalid optional parameter provided:}{} \msg{3}{invalid language requested: ``\CurrentOption''}{} \msg{4}{This is to test the #1 feature}{} \msg{5}{``msg'' package line number }{\msgparti{issues % \#\msgid\ #1 message}} \msg{6}{msg package: UNUSUAL end of file reached when % \MessageBreak % loading \msg@filename\space file!}{} \msg{7}{\string\msg\space syntax error}{\help{last % special test case argument is missing.}} \msgheader{MESSAGE\space\msgid:\space``}\msgtrailer{''} \msg{8}{here is a customized message}{}% \msg{9}{here is a customized message % \MessageBreak which continuation is aligned}{} \msgheader{Message\space\msgid\space(msg):\space}\msgtrailer{} \msg*{10}{****** I emphasize: this is a WARNING! ****** % \MessageBreak ****** Be careful.^^J}{} \msgheader{}\msgtrailer{} \msg{11}{The msg package is in use with ``tracefiles'' option.}{} \msg{12}{A risk of infinite loop arose; % \MessageBreak % please check the message file: \msg@filename}% {\help{Look at rules to apply in messages files.}} \msg{*}{erroneous message id ``\msgid''}{} % % \end{macrocode}\endhard % % If necessary, one can link |english_msg-msg| to that file, but since English % is always the default language for \LaTeX\ this is useless. % % The same messages, localized for French, are located in % \label{msgfiles} % the following messages file (|french_msg-msg.tex|): %\hard % \begin{macrocode} %<*french> % Fichier french_msg-msg.tex % Ici on trouve les messages en francais pour l'extension \msgname\ . % \msgencoding{}\msgheader{}\msgtrailer{} \msg{1}{\filedate\space chargement de l'extension de % localisation (\fileversion).}{} \msg{2}{le param\`etre optionnel est invalide}{} \msg{3}{le langage demand\'e (\CurrentOption) n'existe pas}{} \msg{4}{Ceci est pour tester le dispositif #1}{} \msg{5}{ligne }{\msgparti{de l'extension ``msg'' g\'en\`ere le % message de #1 \#\msgid}} \msg{6}{extension msg \string: fin ANORMALE de fichier rencontr\'ee % \MessageBreak % en chargeant le fichier \msg@filename\space\string!}{} \msg{7}{erreur de syntaxe \`a l'appel de \string\msg}% cas special de test {\help{il manque le dernier argument.}} \msgheader{MESSAGE\space\msgid\space\string:\space % \string<\string<\space} \msgtrailer{\space\string>\string>} \msg{8}{ceci est un message personnalis\'e}{} \msg{9}{ceci est un message personnalis\'e % \MessageBreak et align\'e}{} \msgheader{Message\space\msgid\space(msg)\space\string: % \space}\msgtrailer{} \msg*{10}{****** Je mets en valeur \string: % ceci est un AVERTISSEMENT ! ****** % \MessageBreak ****** Soyez prudent.^^J}{} \msgheader{}\msgtrailer{} \msg{11}{L'extension msg est en service avec l'option % \string<\string< tracefiles \string>\string>.}{} \msg{12}{Un risque de boucle infinie a \'et\'e rencontr\'e \string; % \MessageBreak % v\'erifier le fichier des message \string: \msg@filename}% {\help{Voir les r\`egles \`a appliquer dans les fichiers de messages.}} \msg{*}{le message id ``\msgid'' n'est pas r\'epertori\'e}{} % % \end{macrocode}\endhard % %<*code> % \bigskip % % Notice that you can have messages which call any internal macro name % since the |\catcode| for |@| is assigned to letter when the message % file is read in. % % \ifguide\else % As you see, these files mostly contain |\msg| calls with three % arguments, so it's time now to look at this code. % % Notice that we don't use the real filenames in the above % |<*...>| tags since they contain an underscore character which % is not protected at this level when using the \textsl{ltxdoc} % document class. % \fi % % \section{The macros to use in message files} % % The simpliest way to code a message is: % \begin{center} % \fbox{\texttt{\textbackslash msg\{<\emph{id}>\}\{<\emph{message}>\}\{\}}} % % \end{center} % % The last message in the file should have \texttt{<\emph{id}>} equal % to \texttt* to say that, when reached, no valid \texttt{<\emph{id}>} % was found in the file and % the \msgname\ package should issue (or get or retrieve) that % error \texttt{\emph{message}}, which could be % e.g. |\msg{*}{erroneous message id ``\msgid''}|. % % \begin{macrocode} \catcode`\#=\active\def\set@argmsg{\def#1{\@argmsg}}% \catcode`\#=6% % \end{macrocode} % \begin{macro}{\msg}|#1#2#3| % \begin{macrocode} \def\msg{\let\@msg@gobble@space\@gobble% Should apply after firs call. \@ifstar{\def\@msgskip{^^J}\@msg}{\def\@msgskip{}\@msg}}% % \end{macrocode} % \end{macro} % \begin{macrocode} \long\def\@msg#1{\def\@msg@tempc{#1}\catcode`\#=\active% \def\@msg@tempd##1##2\void{\def\@msg@tempd{##2}% \let\@msg@tempe\empty% \ifx\@msg@tempd\empty% \def\@msg@tempe{##1}% \fi}% \@msg@tempd#1\void\relax% \@msg@tempe is the first #1 token. \let\themsgi\empty% We need to clean any \let\themsgii\empty% previous read \let\themsgiii\empty% message parts. \set@argmsg\@msg@% }% \def\@gobble@help#1#2{\@msgparts}% Case 2 lines \msg with \read \long\def\@msg@#1{\def\@msg@tempd{% but not \input. \ifx\@msginput@usual\@@input@msg@filename% \def\space{\noexpand\space}% \protected@edef\msg@header{\msg@header}% \protected@edef\msg@trailer{\msg@trailer}% \else% \edef\msg@header{\msg@header}% \edef\msg@trailer{\msg@trailer}% \fi% \edef\space{ }% \protected@xdef\themsg{% \@msgskip\msg@header#1\msg@trailer}% \def\space{ }% }% \catcode`\#=6\let\@msg@tempb\relax% \def\@msg@tempb{\@ne\tw@\thr@@\sixt@@n\@cclv}% \ifx\msgid\@msg@tempb% Check for any next message request. \global\let\msgid\@msg@tempc% \else% \ifx\msgid\@msg@tempc% Check for the previous id. \if@msgnext\def\msgid{\@ne\tw@\thr@@\sixt@@n\@cclv}% \fi% \fi% \fi% \ifx\msgid\@msg@tempc% Check for the "id". \let\@msgparts@ORnot\@msgparts@% \def\@msg@tempb{\endinput}% \if@msg@pkg@error% % \end{macrocode} % \begin{macro}{\help}|#1| % \begin{macrocode} \let\help\@firstofone% % \end{macrocode} % \end{macro} % \begin{macrocode} \def\@msgparts@ORnot{\endinput\def\@msg@txt@}% \fi% \def\@msg@tempf{}% \expandafter\@msg@tempd% \else\expandafter% \ifx\@msg@tempe*\let\@msgparts@ORnot\@msgparts@% \def\@msg@tempb{\endinput\@msg@tempd% \PackageWarningNoLine{msg}{\themsg% \themsgi\themsgii\themsgiii}% \global\let\@relaxORgobble\@gobble}% \else\let\@msgparts@ORnot\@gobble% \fi% \fi% \catcode`\#=\active \@ifnextchar\protect{\expandafter\@gobble@help}{\@msgparts}% }% % \end{macrocode} % % When the |\msg{*}| is reached the \msgname\ package will issue a % |\PackageWarning| with that message, but no line number is sent % because the message file is still not closed and the current line % number is that from the message file. The message is also forwarded % to the \TeX\ mouth even when an |\issuemsg| was requested. % % \subsection*{To build a \texttt{\textbackslash PackageError} % or \texttt{\textbackslash ClassError} message} % \label{buildPE} % % A |\PackageError| has a message part and a help part; these are % given as the following: % % \begin{minipage}[t]{0.9\textwidth} % \hrule\medskip % \begin{center} % \begin{tabbing} % |\msg{<|\emph{id}|>}{<|\emph{message-part}|>}|\=\kill^^A] % |\msg{<|\emph{id}|>}{<|\emph{message-part}|>}| % \> |{\help{<|\emph{help-part}|>}}| % \end{tabbing} % \end{center} % \medskip % \hrule\medskip % \end{minipage} % % \noindent in that special case you can't build a multi-parts message as % explained in the following section. % % \subsection*{To build a multi-parts message} % % When given, the optional argument provides 3 additional message parts. % Here is the syntax : % % \begin{minipage}[t]{0.9\textwidth} % \hrule\medskip % \begin{center} % \begin{tabbing} % |\msg{<|\emph{id}|>}{<|\emph{message-part1}|>}{|\=\kill^^A] % |\msg{<|\emph{id}|>}{<|\emph{message-part1}|>}{| % \> |\msgparti{<|\emph{message-part2}|>}|\\ % \> |\msgpartii{<|\emph{message-part3}|>}|\\ % \> |\msgpartiii{<|\emph{message-part4}|>}}| % \end{tabbing} % \end{center} % (Any |\msgparti*| can be omitted) % \medskip % \hrule\medskip % \end{minipage} % % When retrieved, |\themsg| will contain \emph{message-part1}, % |\themsgi| the \emph{message-part2}, % |\themsgii| the \emph{message-part3} and % |\themsgiii| the \emph{message-part4}. % One can build the wanted message with the mix of these four parts and other % materials. When requested via |\getmsg| or |\issuemsg| the four % parts are sticked in the usual order. % % \ifguide\else % These macros are defined when the last |\msg| argument is read in. % \fi % % \begin{macrocode} \long\def\@msgparts#1{\def\@msg@tempc{\catcode`\#=6% \def\@msg@tempb{\issuemsg[% \PackageError{\@msg@pkg}]{7}(msg)% \endinput}% \expandafter\@msg@tempb% }% \ifx\msg#1% When #1 is \msg it's sure the previous \msg \@msg@tempc% didn't provided the correct arguments. \else% \ifx\msgheader#1\@msg@tempc% ditto for \msgheader \else% \ifx\msgtrailer#1\@msg@tempc% ditto for \msgtrailer \else% \ifx\msgencoding#1\@msg@tempc% ditto for \msgencoding \else% \@msgparts@ORnot{#1}% \fi% \fi% \fi% \fi% \@ifnextchar\space{\@gobble}{}% Gobble any superfluous blank. }% % \end{macrocode} % \begin{macro}{\msgparti}|#1| % \begin{macro}{\msgpartii}|#1| % \begin{macro}{\msgpartiii}|#1| % \begin{macrocode} % \long\def\@msgparts@#1{\long\def\msgparti##1{\xdef\themsgi{##1}}% \long\def\help##1{\xdef\themsgi{\space help=##1}}% \long\def\helpi##1{\xdef\themsgi{\space help=##1}}% \long\def\msgpartii##1{\xdef\themsgii{##1}}% \long\def\msgpartiii##1{\xdef\themsgiii{##1}}% #1\catcode`\#=6\expandafter\@msg@tempb% }% % \end{macrocode} % \end{macro}\end{macro}\end{macro} % % \section*{Input encoding discussion}\label{encodings} % % It is assumed that, defaultly, |\issuemsg| will finally provide a message % to the console (without any encoding). % The macro |\getmsg| is designed for typesetting (usually with an % input encoding). Since % |\retrievemsg|'s target is unknown, display or typesetting, we let % the package or class maker to decide which input encoding has to be % set up. % % If you want to issue a message but not to the console, you should % probably use the macro |\issuemsgx| in place of |\issuemsg|. % % \subsection*{For messages issued to the console} % % If your messages can be coded in 7bits, no problem except that you % probably need to avoid macros like |\aa|, |\oe|, |\ae|, etc. which % can't output as expected on the console or log file. % If your messages use 8bits characters, these 8bits characters will % be output asis (until the \LaTeX\ team introduces a real output % encoding for the console\footnote{The \msgname\ package is already designed % for any output encoding; this is the \texttt{\textbackslash kbencoding} % macro call which can do that (as currently done by my experimental % \texttt{keyboard} package).}). % % \subsection*{For messages to be typeset} % % If any of your messages use at least one 8bits character, you need to % specify which input encoding you are using: % \begin{center} % \fbox{\texttt{\textbackslash msgencoding\{<\emph{input encoding}>\}}} % % \end{center} % you just have to give the name of the input encoding, exactly like % with |\inputencoding| for the \texttt{inputenc} package. % This is usually the first command in the messages file. % % \begin{macro}{\msgencoding}|#1| % \begin{macrocode} \let\@msgencoding\@gobble% Nearly null macro until \AtBeginDocument, \def\msgencoding#1{\ifx\empty#1\else% just disactive 8bits chars. \let\iterateORI\iterate% \def\@msg@encoding{#1}% \ifx\msg@cmd\issuemsg% If there is not output encoding: \ifx\kbencoding\undefined%\inputencoding{ascii}% \def\@msgenc@loop##1##2{\@tempcnta`##1\relax% \loop\catcode\@tempcnta=11% \ifnum\@tempcnta<`##2\relax% \advance\@tempcnta\@ne% \repeat}% \@msgenc@loop\^^A\^^H% \@msgenc@loop\^^K\^^K% \@msgenc@loop\^^N\^^_% \@msgenc@loop\^^?\^^ff% 128-255 %%% \global\let\@originalkbe\relax% \else% %%% \xdef\@originalkbe{\noexpand\kbencoding{\@kbencoding}}% \let\languagename\msg@languagename% \let\msgidORI\msgid% Save current msgid because \kbencoding{#1}% it may issue any message. \let\msgid\msgidORI% Now reset it. \@msg@moretrue% Continue file reading. \fi% \else\let\@latex@infoORI\@latex@info% \let\@latex@info\@gobble% \let\endinputBACK\endinput% \let\endinput\endinputORI% \let\msgidORI\msgid% Save current msgid because \@msgencoding{#1}% it may issue any message. \let\msgid\msgidORI% Now reset it. \let\endinput\endinputBACK% \let\@latex@info\@latex@infoORI% \fi\makeatletter% \let\iterate\iterateORI% \fi% }% \let\@msg@encoding\empty% Unknown current encoding. \ifx\kbencoding\undefined% \AtBeginDocument{\let\@msgencoding\inputencoding}% \let\inputencodingORI\inputencoding% Save \inputencoding code \def\inputencoding#1{\def\@ieg{#1}\let\exec@ieg\relax% Avoid \ifx\@ieg\@previeg\else% to load twice \def\@previeg{#1}% the same encoding file. \def\exec@ieg{\inputencodingORI\@ieg}% \fi% \exec@ieg% }% \else% \AtBeginDocument{\let\@msgencoding\kbencoding}% \fi% % \end{macrocode} % \subsection*{Disadvantage using \texttt{\textbackslash msgencoding}} % % As the \texttt{inputenc} package is automatically loaded when % |\msgencoding| is executed, there is a risk you try loading again % \texttt{inputenc} in the preamble via |\usepackage|. This is the case % if any message was already issued by the \msgname\ package and then % an option clash will occur and force you to put the encoding option % as a global option in |\documentclass|. % % Since \msgname\ is calling |inputenc| there will be real difficulties % to localize the |inputenc| package itself. % \end{macro} % % \section*{The messages file rules} % % Due to the \ifguide |reading| process \else % previous |\read| (page \pageref{readcode}) code \fi % you should apply the following rules in % a message file: % \begin{description} % \item [Rule 1:] A line can be a comment (begining with \%). % \item [Rule 2:] A line can begin with |\msg|,|\msgheader|,|\msgtrailer| % or |\msgencoding|. % \item [Rule 3:] A |\msg| line can be continued on the next line(s), assuming % each one ends with \verb*X %X. % \item [Rule 4:] The following macros: |\msgheader|, |\msgtrailer|, % or |\msgencoding| are always executed. % \item [Rule 5:] Spacing inside |\msgheader| and |\msgtrailer| should be % made only by the use of the macro |\space|. % \item [Rule 6:] Any of these three macros should be expandable at any time. % \item [Rule 7:] No other macro command can begin a line. % \item [Rule 8:] All 8bits characters used should in the range specified % by the macro command |\msgencoding|. % \end{description} % That's all! % % \subsection*{To build messages with header and/or trailer} % % \begin{macro}{\msgheader}|#1|\label{msgtrailerdef} % \begin{macro}{\msgtrailer}|#1|\end{macro}\end{macro} % \begin{macrocode} \def\msgheader#1{\let\reserved@a\relax% \def\msg@header{#1}\protect\@msgHTsptoken}% \def\msgtrailer#1{\let\reserved@a\relax% \def\msg@trailer{#1}\protect\@msgHTsptoken}% \def\@msgHTsptoken{\@ifnextchar\@sptoken{\@msg@gobble@space% \let\@msg@gobble@space\@gobble}% {\let\@msg@gobble@space\@gobble}% }% % \end{macrocode} % % Before any |\msg| call you can specify which header and/or trailer you % want in the following message or messages. You just have to specify them: % % \begin{minipage}[t]{0.4\textwidth} % \hrule\medskip % \begin{center} % |\msgheader{<|\emph{my\_header}|>}|\\ % |\msgtrailer{<|\emph{my\_trailer}|>}| % \end{center} % \hrule\medskip % \end{minipage} % % When a message needs to be continued on the next line you just % have to insert |\MessageBreak| where you want the new line will % start and then the \msgname\ package will try to align the following % text by adding the same number of |\space|s as tokens in the % expanded |\msgheader|. That feature only applies with |\issuemsg| and % only to the |<|\emph{message-part1}|>| (the three other message parts % can not have any header or trailer). % % \subsection*{To emphasize a message} % % When you want to emphasize a message you just have to code the star form of % the |\msg| macro: % % \begin{minipage}[t]{0.9\textwidth} % \hrule\medskip % \begin{center} % \begin{tabbing} % |\msg*{<|\emph{id}|>}{<|\emph{message-part1}|>}|\=\kill^^A] % |\msg*{<|\emph{id}|>}{<|\emph{message-part1}|>}| % \> |{<|\emph{part2}|}>}| % \end{tabbing} % \end{center} % \hrule\medskip % \end{minipage} % % and then the message will be issued after a line skip on the console and log. % If your message ends with |^^J| another line will be skiped after. % Obviously this feature only works with |\issuemsg| but not with % |\getmsg| or |\retrievemsg|. % % \subsection*{Examples \& tests} % % We use message \# 5 of |msg-msg.tex| file as following: % % \noindent % \def\foo#1{\retrievemsg5(msg)[#1]\themsg\the\inputlineno\ \themsgi} % |\def\foo#1{\retrievemsg5(msg)[#1]\themsg\the\inputlineno\ \themsgi}| % % \medskip\noindent % then |\emph{The \foo{test}}| will generate: % % \centerline{The \emph{\foo{test}}} % % \noindent % In a French document, the code |\emph{La \foo{test}}| will issue: % % \bgroup\makeatletter\def\msg@languagename{french} % \centerline{\emph{La \foo{test}}} % \egroup % % \medskip % We will now use the message \# 8 of |msg-msg.tex| file in order % to show the customization set in that file. % % \medskip\noindent % |\getmsg8(msg)| will generate:\\ % \getmsg8(msg) % % The following |\texttt{\getmsg9(msg)}| using % |\MessageBreak| will give at the console:\\% % {\catcode`^^J=\active\let^^J\\%^^A We try to simulate the output console. % \def\@msgalspace{\hbox{\space}}%^^A In order to simule \obeyspaces % \def\space{\@sptoken}%^^A we used \space in \msgheader argument. % \def\MessageBreak{^^J\expandafter\@msgalign\msg@header\void% % \hbox{\space}}%^^A Please explain this tt behaviour... % \texttt{\getmsg9(msg)}\\% % } % (same message issued to the console\issuemsg9(msg)).%^^A Issue it really. % % \noindent % And in a French document, the same calls will issue:\\ % \bgroup\makeatletter\def\msg@languagename{french}% % \getmsg8(msg)\\% % \catcode`<=12\catcode`>=12\relax%^^A To remove ltxdoc active chars. % \catcode`^^J=\active\let^^J\\%^^A We try to simulate the output console. % \def\@msgalspace{\hbox{\space}}%^^A In order to simule \obeyspaces % \def\space{\@sptoken}%^^A We try to simulate the output console. % \def\MessageBreak{^^J\expandafter\@msgalign\msg@header\void% % \hbox{\space}}%^^A Please explain this tt behaviour... % \texttt{\getmsg9(msg)} % % \egroup % % Below is a test of an emphasized message (|\texttt{\getmsg{10}(msg)}|): % % {\catcode`^^J=\active\let^^J\\%^^A We try to simulate the output console. % \def\msg{\@ifstar{\def\@msgskip{\\}\@msg}{\def\@msgskip{}\@msg}}% % \def\@msgalspace{\hbox{\space}}%^^A In order to simule \obeyspaces % \def\space{\@sptoken}%^^A we used \space in \msgheader argument. % \def\MessageBreak{^^J\expandafter\@msgalign\msg@header\void% % \hbox{\space}}%^^A Please explain this tt behaviour... % \noindent\texttt{\getmsg{10}(msg)}% % } % (same message issued to the console\issuemsg{10}(msg)). % % \section{Testing a message file} % % % When you are building a messages file few typing errors can occur; so % there is a need to test that file. You can do this by using the % following macro call: % % \begin{center} % \fbox{{\texttt{\textbackslash issueallmsg[<\emph{message\_macro}>](<\emph{package}>)}}} % \end{center} % % All messages will be retrieved and issued as requested (with the message % macro) but not, perhaps, with the exact macro call which will be used in the % \LaTeXe\ package or document class. Specially, the |\help| macro call % does nothing and |\msgpart|s are listed in the order found in the file. % You should also notice that all macros used inside the % messages should be expandable. This macro is allways executed with % the \texttt{tracefiles}\footnote{I never found the right code % to avoid a loop with % \texttt{tracefiles} option...} option. % % Here is an example using the \msgname\ file % (|\issueallmsg[\wlog](msg)|)% % \wlog{^^J **************** Testing the file *************}% % \issueallmsg[\wlog](msg) % \wlog{^^J **************** The End of test *************}% % please check the log file to find the output. % % \begin{macro}{\issueallmsg}|[#1](#2)|\label{issueallmsg} % \begin{macrocode} \def\issueallmsg{\bgroup\let\@@input@msg@filename\@msginput@usual% \let\msg@cmd\issuemsg% \@ifnextchar[{\i@sueallmsg}{\i@sueallmsg[\issuemsgio]}%] }% \def\i@sueallmsg[#1]{\let\@msg@iocmdn#1\i@@ueallmsg}% \def\i@@ueallmsg(#1){\def\next{\i@@@eallmsg(#1)}% \long\def\help##1{\xdef\themsgi{\space help=##1}}% \let\if@msgnext\iftrue% begin/continue loop. \def\msgid{\@ne\tw@\thr@@\sixt@@n\@cclv}% Set next one wanted. \let\prev@msgid\msgid% Save previous id. \i@@@eallmsg(#1)% Go for looping. \let\if@msgnext\iffalse% }% \def\i@@@eallmsg(#1){\def\@tempa{\i@@uemsg[\@msg@iocmdn]}% \let\themsg\empty% \expandafter\@tempa\expandafter{\msgid}(#1)[]% Get it. \def\@tempa{\let\if@msgnext\iffalse}% \ifx\prev@msgid\msgid% \@tempa% \let\@@input@msg@filename\@msginput@usual% \issuemsg[\PackageError{msg}]{12}(msg)% \expandafter\stop% \fi% \let\prev@msgid\msgid% Save previous id. \def\@tempa{*}% Check if last one. \ifx\msgid\@tempa% \let\next\egroup% This is the end. \fi% \let\msg@cmd\issuemsg% \next% }% % \end{macrocode} % \end{macro} % \section{Output options} % % \begin{center} % \fbox{\texttt{\textbackslash usepackage[<\emph{output-options}>]\{msg\}}}% % \end{center} % % The output options provide to the \msgname\ package with a running % macro name to issue any message, in replacement of the default % |\issuemsgio| macro initialized at the begining (cf page~\pageref{msgio}). % Currently the following macro names are defined as options: % % \begin{center} % \def|{$\mid$} % \fbox{\texttt{\textbackslash usepackage[message|wlog|typeout|kbtypeout]\{msg\}}}% % \end{center} % % \begin{macrocode} \ifx\intern@lc@llfrom\undefined% Options aren't declared for internal/kernel calls \DeclareOption{message}{\let\issuemsgio\message}% TeX cs. \DeclareOption{wlog}{\let\issuemsgio\wlog}% Plain TeX cs. \DeclareOption{typeout}{\let\issuemsgio\typeout}% LaTeX cs. \DeclareOption{kbtypeout}{\let\issuemsgio\kbtypeout}% Keyboard cs. \fi% % \end{macrocode} % % These options are related to basic messages macros but this % is not an exhaustive list of macros which can be called by % |\issuemsg|. Specially, |\PackageError| can also be used, % as already discussed p.~\pageref{willingPE} and p.~\pageref{buildPE}. % The last one macro name is coming from a package of mine % (\textsf{keyboard}) doing input encoding and output decoding. % % \section{A tracing option} % % \begin{center} % \fbox{\texttt{\textbackslash usepackage[<\emph{tracefiles}>]\{msg\}}}% % \end{center} % % The \texttt{tracefiles} option changes the processing for reading % messages files. Defaultly these files are not read with the usual % |\input| macro and so the files are not listed in the \texttt{log} % file. When giving the \texttt{tracefiles} option messages files % are read with a |\input| macro like and then the full path names % are listed. % % \begin{macrocode} \ifx\intern@lc@llfrom\undefined% Options aren't declared for internal/kernel calls \DeclareOption{tracefiles}{\let\@@input@msg@filename\@msginput@usual}% \fi% % \end{macrocode} % % \section{A special option} % % \begin{center} % \fbox{\texttt{\textbackslash usepackage[<\emph{noop}>]\{msg\}}}% % \end{center} % % The \texttt{noop} option changes the processing: don't read the % messages files and just provides the "msgid" as text message with % the following header: |0|. % % \begin{macrocode} \ifx\intern@lc@llfrom\undefined% Options aren't declared for internal/kernel calls \DeclareOption{noop}{\def\@@input@msg@filename{\xdef\themsg{0}% \xdef\themsgi{\string\space\msgid}% }% }% \fi% % \end{macrocode} % % \section{Language options} % % \begin{center} % \fbox{\texttt{\textbackslash usepackage[<\emph{output-options}>,<\emph{language-name}>]\{msg\}}}% % \end{center} % % Defaultly messages are issued from the message file dedicated to the % document running language. One can force the \msgname\ package to use % a specific language (assuming it was defined in the \texttt{language.dat} % file in use), just give it as the last option. % % \begin{macro}{\nativelanguage}|#1|\end{macro} % \begin{macrocode} \edef\nativelanguage{french}% This is my native language. % \end{macrocode} % This optional macro is usefull to understand and/or translate % correctly the message files. Each package writer can define it % as i currently do for the \msgname\ package here. To obtain messages % in writer's native language, just call the \msgname\ package with % the option `|native|': % % \begin{center} % \fbox{\texttt{\textbackslash usepackage[<\emph{output-options}>,native]\{msg\}}}% % \end{center} % % \ifguide\else % The previous line of code declares |french| as an option for the \msgname\ % package itself. Going this way we redefine |\packagewarning| we set at % the begining page~\pageref{pw} and translate |\on@line| in French. % I don't suggest to do the same for all other languages... this is just % a native language privilege. % \fi % % \begin{macrocode} \let\on@lineORI\on@line% \let\pwhORI\packagewarningheader% \ifx\intern@lc@llfrom\undefined% Options aren't declared for internal/kernel calls \DeclareOption{french}{% Mostly a testing option % or have msg's messages in French. \@msgINfrench}% \fi% \def\@msgINfrench{% \def\on@line{ (voir le source, ligne \the\inputlineno)}% \def\packagewarningheader##1{Extension ##1 : ATTENTION, }% \def\msg@languagename{french}}% % \end{macrocode} % % \ifguide\else % It may occur that the |\languagename| is already set (e.g. in the % \LaTeX\ format), so we test it; if French is set the \msgname\ package will % then speak that language. % % \begin{macrocode} \edef\@msg@tempa{french}\ifx\languagename\@msg@tempa\@msgINfrench\fi% % \end{macrocode} % Here is the code to process the last option: % \fi % \begin{macrocode} % Last option will be the msg's language if defined (within the % \texttt{language.dat} file in use). \ifx\intern@lc@llfrom\undefined% Options aren't declared for internal/kernel calls \DeclareOption*{% Once a language is provided we should \let\on@line\on@lineORI% reset to default. \let\packagewarningheader\pwhORI% \def\@msg@tempa{native}% \ifx\@msg@tempa\CurrentOption% \let\msg@languagename\nativelanguage% \else% \expandafter% \ifx\csname l@\CurrentOption\endcsname\relax% \def\@msg@tempa{\retrievemsg3(msg)\PackageWarningNoLine{msg}% {\themsg\themsgi\themsgii\themsgiii}}% \else\def\@msg@tempa{\edef\msg@languagename{\CurrentOption}}% \fi\@msg@tempa% \fi% }% \fi% % % \end{macrocode} % The last option, if undeclared as an option, is assumed to be % a language name. If that language is unknown (i.e. undefined % in the \texttt{language.dat} file in use) we issue a warning % with message number 3, % otherwise that language name will be now the prefix for all % the message files names searchs. It overides any previously set % (in format, package, ...) language name for use by the \msgname\ package. % % Notice that, when set (and forced) as option, the \msgname\ language % name can't be changed any way inside the document (no language % change can modify that). % % \ifguide\else % \section{Finally} % % It's time now to process the options, get the \msgname\ package's banner % and issue it as well in the log file. % % That's all for the code. % \fi % % \begin{macrocode} \ifx\intern@lc@llfrom\undefined% No process of options for internal/kernel calls \ProcessOptions% Process options \fi% % Retrieve msg: \filedate\ msg package (\fileversion) loaded. \bgroup% Protect from any setting. \retrievemsg1(msg)% \csname msg@MPC\endcsname% required when ltxdoc \ProvidesPackage{msg}[\themsg]% Issue that message in log file with \def\@msg@tempa{\retrievemsg{11}(msg)\wlog{\themsg}}% options messages. \ifx\@@input@msg@filename\@msginput@usual\expandafter\@msg@tempa\fi% \egroup% % % \end{macrocode} % \section{Migration scheme} % % If you want to migrate a document class ou package issuing messages % in order it could be localized for any language, you just have % to follow the following steps: % % \begin{enumerate} % \item Chose the native language and create the related messages file. % \item Chose the input encoding and define it in the messages file % with the macro |\msgencoding|. % \item Insert the final error message (|\msg(*){...}{}|). % \item Isolate all messages in the code. % \item Attach to each message a unique \textsl{id}. % \item Comment each message argument(s) and put these arguments % in the message file as: \\ % |\msg{|\textsl{id}|}{|\textsl{argument1}|}{<|\textsl{argument2}|>}| % \item Replace the message macro call (|\typeout| or |\wlog| or ...) % by : \\ % |\issuemsg[<|\textsl{message macro}|>]{|\textsl{id}|}(|\textsl{package}|)| % \item Check the syntax carefully, specially, for error messages and % when a parameter will be used. % \item Test each message independtly and tune it considering the % display option, the header and trailer facilities, etc. % \item Test the messages file with |\issueallmsg|. % \item Consider other translations of your native messages file. % \item Release the new code along with its messages files. % \end{enumerate} % % \section{Generated files} % % Currently the file |msg.ins| is the file to compile with (La)TeX % to generate all the \msgname\ stuff. Here is |msg.ins| showing % the |doctrip| generated files: % % \makeatletter% % \def\verbatimfile#1{\begingroup\small\let\check@percent\relax\tt% % \@verbatim\frenchspacing\@vobeyspaces% % \@@input#1\endgroup}% % \makeatother% % \bigskip\hrule % \verbatimfile{msg.ins}% % % \bigskip % \hrule % % \section{Volunteers} % % Volunteers are welcome to translate the \msgname\ package message % file (the English one or the native one in French) in their mother language. % Lot of thanks to them! % % \section{Thanks} % % The following people contributed to that project and we really appreciate % their effort for testing, translating, documenting, etc.: % Hans~F.~Nordhaug, Harald~Harders. % \vfill % Enjoy! % \vfill % \centerline{$*$--$*$} % \vfill % \newpage % \iffalse %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% \CharacterTable %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z %% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z %% Digits \0\1\2\3\4\5\6\7\8\9 %% Exclamation \! Double quote \" Hash (number) \# %% Dollar \$ Percent \% Ampersand \& %% Acute accent \' Left paren \( Right paren \) %% Asterisk \* Plus \+ Comma \, %% Minus \- Point \. Solidus \/ %% Colon \: Semicolon \; Less than \< %% Equals \= Greater than \> Question mark \? %% Commercial at \@ Left bracket \[ Backslash \\ %% Right bracket \] Circumflex \^ Underscore \_ %% Grave accent \` Left brace \{ Vertical bar \| %% Right brace \} Tilde \~ %% And any code from 128 to 255 %% } %% % \fi % \Finale%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%