% \iffalse %\ProvidesPackage{stringstrings} %[2020/12/08 v1.24 % Extensive array of string manipulation routines for % cosmetic and programming application] %\NeedsTeXFormat{LaTeX2e} %<*driver> % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3c or later is part of all distributions of LaTeX % version 2005/12/01 or later. % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is Steven B. Segletes. % % v1.00 -Initial Release % v1.01 -Included support for & character, though it loses catcode 4 % status % v1.02 -Bug fix. Needed some % chars in \convertchar to avoid extra spaces % v1.03 -Documentation fix; notably removed 's' from \narg in \getargs % v1.04 -Removed \rotate command, as it conflicts with environment in % \usepackage{rotating} % v1.10 -Fixed bug in convertword by adding @@@stringsize definition to % \whereisword % -Added suite of routines to support \capitalizetitle functionality % v1.20 -Added ability to encode/decode arbitrary tokens % v1.21 -Added %, removing extra space (bug) from \whereisword % v1.22 -Added %, removing extra space (bug) from \getargs % v1.23 -Changed {~} to {\ } in \retokenizechar % -Forced all stringtest commands to function outside of math mode % which will give correct result, when invoked within math mode. % V1.24 -Added %, removing extra space (bug) from \testmatchingchar \documentclass{ltxdoc} \usepackage{stringstrings} \DisableCrossrefs \CodelineNumbered % DEFINE SOME CAMMANDS THAT ARE EASIER HERE THAN IN DocInput ENVIRONMENT \newcommand\stringstrings{\textsf{stringstrings}~} \newcommand\coolstr{\textsf{coolstr}~} % ITALICIZED i.e., \newcommand{\ie}{\textit{i.e.},~}% % ITALICIZED e.g., \newcommand{\eg}{\textit{e.g.},~}% % ITALICIZED etc. \newcommand{\etc}{\textit{etc}.}% \def\modetablelayout{|l|c|c|c|} \def\mylayout{@{}c|c|l@{}} \stringencode{\|} \stringdecode[q]{\thestring} \edef\mypipe{\thestring} \stringencode{\carat} \stringdecode[q]{\thestring} \edef\mycarat{\thestring} \GetFileInfo{stringstrings.sty} \begin{document} \title{The \stringstrings Package\\ \rule{0em}{0.7em}\small\fileinfo} \author{Steven B. Segletes\\ steven.b.segletes.civ@mail.mil} \date{\filedate\\ \fileversion} \maketitle \DocInput{stringstrings.dtx} \end{document} % %\fi % \parskip 1ex % \begin{abstract} % The \stringstrings package provides a large and sundry array of routines % for the manipulation of strings. The routines are developed not only % for cosmetic application, such as the changing of letter % cases, selective removal of character classes, and string % substitution, % but also for programming application, such as character look-ahead % applications, argument parsing, |\if|-tests for various string % conditions, etc. A key tenet employed during the % development of this package (unlike, for comparison, the |\uppercase| % and |\lowercase| routines) was to have resultant strings be % ``expanded'' (\ie the product of an |\edef|), so that the % \stringstrings routines could be strung together sequentially and % nested (after a fashion) to achieve very complex manipulations. % % \end{abstract} % % \vspace{-.55em} % \tableofcontents\rule[.2em]{4.5in}{.3mm}\vspace{-1.5em} % % \section {Motivation} % % There were two seminal moments that brought about my motivation to % develop this package. The first was the realization of the oft % cited and infamous \LaTeX{} limitation concerning the inability to % nest letter-case changes with \LaTeX{}'s intrinsic |\uppercase| and % |\lowercase| routines. The second, % though not diminishing its utility in many useful applications, was % the inherent limitations of the \coolstr package, which is otherwise % a useful tool for extracting substrings and measuring string lengths. % % The former is well documented and need not be delved into in great % detail. Basically, as it was explained to me, |\uppercase| and % |\lowercase| are expanded by \LaTeX{} at the last possible moment, and % thus attempts to capture their result for subsequent use are doomed to % failure. One is forced to adopt the left-to-right (rather than % nested) approach to case changes. % % In the case of the \coolstr package, I again want to express % my admiration for the utility of this package. I briefly considered % building the \stringstrings package around it, but it proved % unworkable, because of some intrinsic limitations. % First, \coolstr operates on % strings, not tokens, and so in order to fool it into working on % tokenized inputs, one must use the cumbersome nomenclature of % % |\expandafter\substr\expandafter{\TokenizedString}{...}{...}| % \vspace{1ex}\\% % in order to, for example grab a substring of |\TokenizedString|. One % may |\def| the result of this subroutine, and use it elsewhere in an % unaltered state. However, one may not expand, via |\edef|, the % result of |\substr| in order to use it as input to a subsequent string % manipulation. And thus, the desire to engage in successive string % manipulations of different natures (\eg capitalization of leading % characters, extraction of words, reversal of character sequence, % removal of character classes, etc., etc.) are not achievable in the % context of \textsf{coolstr}. % % It was this state of affairs that brought me to hunger for routines % that could thoroughly manipulate strings, and yet produce their result % ``in the clear'' (\ie in an untokenized form) which could be used as % input for the next manipulation. It turns out the heart of the % \stringstrings package which achieves this goal is based on the simple % (if much maligned) |\if| construct of \LaTeX{}, by using successive % iterations of the following construct: % % |\if <|\textit{test char.}|><|\textit{string}|><|\textit{manipulated % test char.}|>\else ...\fi| % \vspace{1ex}\\% % in which a character at the begining of a string is tested. If a % match is found, % the manipulated test character is replaced at the end of the string, % while the original test character is lopped off from the beginning of % the string. A false result is used to proceed to a different test % character. In this manner, the string may be rotated through, % character by character, performing the desired manipulations. And, % most importantly, the product of this operation may be placed into an % |\edef|. % % It turns out there was one glitch to this process (which has been % successfully remedied in the \stringstrings package). And that is that % there are several tokenized \LaTeX{} symbols (\eg |\$|, |\{|, |\}|, % |\AE|, |\oe|, etc.) which expand to more than a single byte. If % I was more savvy on \LaTeX{} constructs, I would probably have known % how to handle this better. But my solution was to develop my own % encoding scheme wherein these problematic characters were re-encoded % in my intermediate calculations as a 2-byte (escape character-escape code) % combination, and only converted back into \LaTeX{} symbols at the last % moment, as the finalized strings were handed back to the user. % % There are also several tokens, like |\dag|, |\ddag|, |\P|, |\d|, |\t|, % |\b|, and |\copyright| which % can not be put into an |\edef| construct. The solution developed for % strings containing these such characters was to convert the encoded % string not into an expanded |\edef| construct, but rather back into a % tokenized form amenable to |\def|. The |\retokenize| command % accomplishes this task and several others. % % There was also one glitch that I have not yet been able to resolve % to my full satisfaction, though I have provided a workaround. % And that is the occurance of \LaTeX{} grouping characters, |{| and % |}|, that might typically occur in math mode. The problem is that the % character-rotate technique that is the core of \stringstrings breaks % when rotating these group characters. Why?? Because a string % comprised of |...{...}...|, during the rotation process, will % eventually become |...}......{| during an intermediate stage of % character rotation. This % latter string breaks \LaTeX{} because it is not a properly constructed % grouping, even if subsequent rotations would intend to bring it back % into a proper construction. % % And so, while \stringstrings can handle certain math-mode % constructs (\eg |$|, |^|, and |_|), it is unable to {\it directly} % handle groupings that are brought about by the use of curly braces. % Note that |\{| and |\}| are handled just fine, but not |{| and |}|. % As a result of this limitation regarding the use of grouping braces % within strings, \stringstrings support for various math symbols % remains quite limited. % % While it is also common to use curly braces to % delimit the arguments of diacritcal marks in words like % |m\"{u}de| \etc, the same result can be achieved without the % use of braces as |m\"ude|, with the proper result obtained: m\"ude. % For diacritical marks that have an alphabetic token such as the breve, % given by |\u|, the curly braces can also be omitted, with the only % change being a space required after the |\u| to delimit the token. % Thus, |c\u at| becomes c\u at. Therefore, when manipulating strings % containing diacritical marks, it is best to formulate them, if % possible, without the use of curly braces. % % The workaround fix I have developed, to provide grouping functions % within \stringstrings arguments, involves the use of newly defined % tokens |\LB| and |\RB| (to be used in lieu of |{| and |}|), % along with a command |\retokenize|. This % workaround will be described subsequently, in the Disclaimers section. % % \section{Philosophy of Operation} % % There are several classes of commands that have been developed as part % of the \stringstrings package. In addition to {\bf Configuration % Commands}, which set parameters for subsequent string operations, % there are the following command classes: % \begin{itemize} % \item {\bf Commands to Manipulate Strings} -- these commands take an % input string or token and perform a specific manipulation on the % string; % \item {\bf Commands to Extract String Information} -- these commands % take an input string or token, and ascertain a particular % characteristic of the string; and % \item {\bf Commands to Test Strings} -- these commands take an input % string or token and test for a particular alphanumeric condition. % \end{itemize} % Of course, there are also {\bf Support Commands} which are low-level % routines which provide functionality to the package, which are % generally not accessible to the user. % % To support the intended philosophy that the user may achieve a complex % string manipulation though a series of simpler manipulations (which % is otherwise known as nesting), a mechanism had to be developed. True % command nesting of the form |\commandA{\commandB{\commandC{string}}}| % is {\bf not} supported by the \stringstrings package, since many of % the manipulation commands make use of (and would thus inadvertantly % overwrite) the same sets of variables used by other routines. % Furthermore, there is that 'ol left-to-right philosophy of \LaTeX{} to % contend with. % % Instead, for the case of commands that manipulate strings, the expanded % (\ie |\edef|'ed) result of the manipulation is placed into a string % called |\thestring|\DescribeMacro{\thestring}. Then, |\thestring| % may either be directly used % as the input to a subsequent operation, or |\edef|'ed into another % variable to save it for future use. % % String manipulation commands use an optional first argument to specify % what to do with the manipulated string (in addition to putting it in % |\thestring|). Most string manipulation % commands default to verbose mode |[v]|\DescribeMacro{[v]}, and print % out their result immediately on the assumption that a simple string % manipulation is, many times, all that is required. If the user wishes % to use the manipulated result as is, but needs to use it later in the % document, a quiet mode |[q]| \DescribeMacro{[q]} is provided which % suppresses the immediate output of |\thestring|. % % In the absence of symbol tokens (\eg |\$|, |\&|, |\oe|, |\^|, \etc), % the verbose and quiet modes would prove sufficient. However, when a % tokenized symbol is |\edef|'ed, the token is expanded to the actual % symbolic representation of the character. If this expanded symbol is % used as part of an input string to a % subsequent \stringstrings manipulation % routine, it gets confused, because the means to detect the token are % characteristically different than the means to detect the expanded % symbol. Thus, if one wishes to use |\thestring| as an input to a % subsequent manipulation routine, \stringstrings provides an encoded % mode |[e]| \DescribeMacro{[e]} which places an encoded version of the % resulting manipulation into % |\thestring|. The encoded mode is also a quiet mode, since it leaves % |\thestring| in a visually unappealing state that is intended for % subsequent manipulation. % % The encoded mode is not a \LaTeX{} standard, % but was developed for this application. And therefore, if the result % of a \stringstrings manipulation is needed as input for a routine % outside of the \stringstrings package, the encoded mode will be of no % use. For this reason (and others), % the |\retokenize| \DescribeMacro{\retokenize} % command is provided. Its use is one of only three times that a % \stringstrings command % returns a tokenized |\def|'ed string in |\thestring|, rather than an % expanded, |\edef|'ed string. And in the other two cases, both % call upon |\retokenize|. % % In addition to providing tokenized strings that can be passed to other % \LaTeX{} packages, |\retokenize| can also remedy \stringstrings problems % associated with inadequate character encodings (OT1) and the use of % grouping characters |{| and |}| within \stringstrings arguments. This % issue is discussed more fully in the Disclaimers section, and in the % actual |\retokenize| command description. % % Therefore, for complex multistage string manipulations, the % recommended procedure % is to perform each stage of the manipulation in encoded |[e]| mode, % passing along |\thestring| to each subsequent stage of the % manipulation, until the very last manipulation, which should be, % at the last, performed in verbose |[v]| or quiet |[q]| modes. If % the resulting manipulation is to be passed to a command outside of the % \stringstrings package for further manipulation (or if the string % contains characters which cannot be placed into an |\edef|), % |\thestring| may % need to be |\retokenize|'ed. If concatenations of two (or more) different % manipulations are to be used as input to a third manipulation, % |\thestring| from the first manipulation will need to be immediately % |\edef|'ed into a different variable, since |\thestring| will be % overwritten by the second manipulation (see Table~\ref{tbl:modes} % for summary). % \begin{table}[h] % \begin{center} % \caption{\bf Execution Modes of \stringstrings Commands % \label{tbl:modes}}\vspace{0.5em} % \small % \begin{tabular}\modetablelayout % \hline % Mode & Coding & Use when result is & |\thestring| is\\ % \hline % \hline % |[v]| verbose & decoded or retokenized & final & echoed \\ % |[q]| quiet & decoded or retokenized & final & not echoed \\ % |[e]| encoded & encoded & intermediate & not echoed \\ % \hline % \end{tabular} % \end{center} % \end{table} % % Moving on to commands that extract string information, this class of % commands (unless otherwise noted) output their result into a token % which is given the name |\theresult|\DescribeMacro{\theresult}. % This token does not contain a manipulated form of the string, but % rather a piece of information about the string, such as ``how many % characters are in the string?'', ``how many words are in the string?'', % ``how many letter `e's are in the string?'', \etc % % The final class of \stringstrings commands are the string-test % commands. While some of this class of commands also store their % test result in |\theresult|, most of these commands use the % |\test|{\it condition}|{|{\it string}|}| |\if|{\it % condition} constructs (see {\sf ifthen} package) to answer true/false % questions like ``is the string composed entirely of lowercase % characters?'', ``is the string's first letter capitalized?'' \etc % % \section {Configuration Commands} % % \noindent% % |\Treatments{|{\it U-mode}|}{|{\it l-mode}|}{|{\it p-mode}|}{|{\it% % n-mode}|}{|{\it s-mode}|}{|{\it b-mode}|}|\\ % |\defaultTreatments|\\ % |\encodetoken[|{\it index}|]{|{\it token}|}|\\ % |\decodetoken[|{\it index}|]{|{\it token}|}|\\ % |\+|\\ % |\?| % % The command |\Treatments| \DescribeMacro{\Treatments} % is used to define how different classes of % characters are to be treated by the command |\substring|, which is the % brains of the \stringstrings package. As will be explained in the % next section, most string manipulation routines end up calling % |\substring|, the difference between them being a matter of how these % character treatments are set prior to the call. % Because most string manipulation % commands will set the treatments as necessary to perform their given % task, and reset them to the default upon conclusion, one should set % the |\Treatments| immediately prior to the call upon |\substring|. % % |\Treatments| has six arguments, that define the mode of treatment % for the six classes of characters that \stringstrings has designated. % All modes are one-digit integers. They are described below: % \begin{itemize} % \item{\it U-mode---} This mode defines the % treatment for the upper-case characters (A--Z, \OE, \AE, \AA, \O, and % \L). % A mode of 0 tells |\substring| to remove upper-case characters, a % mode of 1 indicates to leave upper-case characters alone, and % a mode of 2 indicates to change the case of upper-case % characters to lower case. % % \item {\it l-mode---} This mode defines the % treatment for the lower-case characters (a--z, \oe, \ae, \aa, \o, \l, % and \ss). % A mode of 0 tells |\substring| to remove lower-case characters, a % mode of 1 indicates to leave lower-case characters alone, and % a mode of 2 indicates to change the case of lower-case % characters to upper case. In the case of the eszett character (\ss), % there is no uppercase equivalent, and so an {\it l-mode} of 2 will % leave the eszett unchanged. % % \item {\it p-mode---} This mode defines the % treatment for the punctuation characters. \stringstrings % defines the punctuation characters as ; : ' " , . ? ` and ! A mode of % 0 tells |\substring| to remove punctuation characters, while a mode of % 1 indicates to leave punctuation characters as is. % % \item {\it n-mode---} This mode defines the % treatment for the numerals (0--9). A mode of % 0 tells |\substring| to remove numerals, while a mode of % 1 indicates to leave numerals as is. % % \item {\it s-mode---} This mode defines the % treatment for the symbols. \stringstrings % defines symbols as the following characters and diacritical marks: % \substring{/ * ( ) - = + [ ] $<$ $>$}{1}{$} \& |\& \% \# \{ \} \_ \$| % \dag~\ddag~\S~\P~\L~\pounds~\copyright~\v x \^x \~x \"x \`x \'x \=x % \.x \u x \v x % \H x \c x \d x \t{xx} \b x as well as |@|, math and text carats, % and the pipe symbol. A mode of % 0 tells |\substring| to remove symbols, while a mode of % 1 indicates to leave symbols as is. Note that the \$ symbol, when % used for entering and exiting math mode, is left intact, regardless of % {\it s-mode}. % % % \item {\it b-mode---} This mode defines the % treatment for blankspaces. A mode of % 0 tells |\substring| to remove blankspaces, while a mode of % 1 indicates to leave blankspaces as is. The treatment apples to both % soft (~) as well as hard (|~|) spaces. % \end{itemize} % % The command |\defaultTreatments| \DescribeMacro{\defaultTreatments} % resets all treatment modes to their default settings, which are to % leave individual characters unaltered by a string manipulation. % % The commands |\encodetoken| \DescribeMacro{\encodetoken} and % |\decodetoken| \DescribeMacro{\decodetoken} have been introduced in % \stringstrings v1.20. Prior to this version, the ability of % \stringstrings to handle a particular token was dependent on whether % provisions for encoding that token had been explicitly hardwired into % the \stringstrings package. A large number of alphabetic and % diacritical marks had reserved encodings set aside in \stringstrings % for their treatment (see next paragraph or Table 2 for their enumeration). % However, requests would invariable come in for treating yet another % token, which required a new \stringstrings release for each revision. % The command |\encodetoken| allows the user to specify an arbitrary % token, to be assigned to the reserved encoding slot associated with the % index (permissible indices are in the range 1--3, 1 being the default). % Once assigned an encoding slot, a token may be successfully manipulated in % \stringstrings routines. Once \stringstrings manipulation is % complete, the token must undergo a |\decodetoken| operation in order % for that token to be reset to a normal \LaTeX{} token again (lest it % display in its encoded \stringstrings form). % % The commands |\+| and |\?| \DescribeMacro{\+}\DescribeMacro{\?} % are a pair that work in tandem to turn on \stringstrings encoding and % turn off \stringstrings encoding, respectively. Generally, the user % will not need these commands unless he is writing his own routines to % take advantage of the \stringstrings library. After |\+| is called, % tokens which would otherwise expand to multi-byte sequences are % instead encoded according to the \stringstrings methodology. The % affected tokens % include % |\$ \^ \" \{ \} \_ \dag \ddag \P \S \ss \AA \aa \O \o \AE \ae| % |\OE|, |\oe|, |\~|, |\`|, |\'|, |\=|, |\.|, |\u|, |\v|, |\H|, |\c|, % |\d|, |\t|, |\b|, |\copyright|, |\pounds|, |\L|, |\l|, and |\ss|. In % addition, pipes, text carats, and hard spaces (|~|) are encoded % as well. The command |\?| restores the % standard \LaTeX{} encoding for these tokens. % % \section {Commands to Manipulate Strings} % % These commands take an % input string or token and perform a specific manipulation on the % string. They include: % % \noindent|\substring[|{\it mode}|]{|{\it % string}|}{|{\it min}|}{|{\it max}|}|\\ % |\caseupper[|{\it mode}|]{|{\it string}|}|\\ % |\caselower[|{\it mode}|]{|{\it string}|}|\\ % |\solelyuppercase[|{\it mode}|]{|{\it string}|}|\\ % |\solelylowercase[|{\it mode}|]{|{\it string}|}|\\ % |\changecase[|{\it mode}|]{|{\it string}|}|\\ % |\noblanks[|{\it mode}|]{|{\it string}|}|\\ % |\nosymbolsnumerals[|{\it mode}|]{|{\it string}|}|\\ % |\alphabetic[|{\it mode}|]{|{\it string}|}|\\ % |\capitalize[|{\it mode}|]{|{\it string}|}|\\ % |\capitalizewords[|{\it mode}|]{|{\it string}|}|\\ % |\capitalizetitle[|{\it mode}|]{|{\it string}|}|\\ % |\addlcword{|{\it word}|}|\\ % |\addlcwords{|{\it word1 word2 word3 \ldots}|}|\\ % |\resetlcwords|\\ % |\reversestring[|{\it mode}|]{|{\it string}|}|\\ % |\convertchar[|{\it mode}|]{|{\it % string}|}{|{\it from-char}|}{|{\it to-string}|}|\\ % |\convertword[|{\it mode}|]{|{\it % string}|}{|{\it from-string}|}{|{\it to-string}|}|\\ % |\rotateword[|{\it mode}|]{|{\it string}|}|\\ % |\removeword[|{\it mode}|]{|{\it string}|}|\\ % |\getnextword[|{\it mode}|]{|{\it string}|}|\\ % |\getaword[|{\it mode}|]{|{\it string}|}{|{\it n}|}|\\ % |\rotateleadingspaces[|{\it mode}|]{|{\it string}|}|\\ % |\removeleadingspaces[|{\it mode}|]{|{\it string}|}|\\ % |\stringencode[|{\it mode}|]{|{\it string}|}|\\ % |\stringdecode[|{\it mode}|]{|{\it string}|}|\\ % |\gobblechar[|{\it mode}|]{|{\it string}|}|\\ % |\gobblechars[|{\it mode}|]{|{\it string}|}{|{\it n}|}|\\ % |\retokenize[|{\it mode}|]{|{\it string}|}| % % \noindent % Unless otherwise noted, the {\it mode} may take one of three values: % |[v]| for verbose mode (generally, the default), |[q]| for quiet mode, % and |[e]| for encoded mode. In all cases, the result of % the operation is stored in |\thestring|. In verbose mode, it is also % output immediately (and may be captured by an |\edef|). In quiet mode, % no string is output, though the result still resides in |\thestring|. % Encoded mode is also a quiet mode. However, the encoded mode saves % the string with its \stringstrings encodings. Encoded mode indicates % that the result is an intermediate result which will be subsequently % used as input to another \stringstrings manipulation. % % The command |\substring| \DescribeMacro{\substring} is the brains of % the \stringstrings package, in that most of the commands in this % section call upon |\substring| in one form or another. Nominally, the % routine returns a substring of {\it string} between the characters % defined by the integers {\it min} and {\it max}, inclusive. % However, the returned substring is % affected by the designated |\Treatments| which have been defined % for various classes of characters. Additionally, a shorthand of \$ % may be used in {\it min} and {\it max} to define END-OF-STRING, and % the shorthand \$--{\it integer} may be used to define an offset of % {\it integer} relative to the END-OF-STRING. % % Regardless of how many bytes a \LaTeX{} token otherwise expands % to, or how many characters are in the token name, each \LaTeX{} % symbol token % counts as a single character for the purposes of defining the % substring limits, {\it min} and {\it max}. % % While the combination of |\Treatments| and |\substring| are sufficient % to achieve a wide array of character manipulations, many of those % possibilities are useful enough that separate commands have been % created to describe them, for convenience. Several of the commands % that follow fall into this category. % % The command |\caseupper| \DescribeMacro{\caseupper} takes the input % string or token, and converts all lowercase characters in the string % to uppercase. All other character classes are left untouched. % Default mode is |[v]|. % % The command |\caselower| \DescribeMacro{\caselower} takes the input % string or token, and converts all uppercase characters in the string % to lowercase. All other character classes are left untouched. % Default mode is |[v]|. % % The command |\solelyuppercase| \DescribeMacro{\solelyuppercase} is % similar to |\caseupper|, except that all punctuation, numerals, and % symbols are discarded from the string. Blankspaces are left alone, % and lowercase characters are converted to uppercase. % Default mode is |[v]|. % % The command |\solelylowercase| \DescribeMacro{\solelylowercase} is % similar to |\caselower|, except that all punctuation, numerals, and % symbols are discarded from the string. Blankspaces are left alone, % and uppercase characters are converted to lowercase. % Default mode is |[v]|. % % The command |\changecase| \DescribeMacro{\changecase} switches lower % case to upper case and upper case to lower case. All other characters % are left unchanged. % Default mode is |[v]|. % % The command |\noblanks| \DescribeMacro{\noblanks} removes blankspaces % (both hard and soft) from % a string, while leaving other characters unchanged. % Default mode is |[v]|. % % The command |\nosymbolsnumerals| \DescribeMacro{\nosymbolsnumerals} % removes symbols and numerals from % a string, while leaving other characters unchanged. % Default mode is |[v]|. % % The command |\alphabetic| \DescribeMacro{\alphabetic} discards % punctuation, symbols, and numerals, while retaining alphabetic % characters and blankspaces. % Default mode is |[v]|. % % The command |\capitalize| \DescribeMacro{\capitalize} turns the first % character of {\it string} into its upper case, if it is alphabetic. % Otherwise, that character will remain unaltered. % Default mode is |[v]|. % % The command |\capitalizewords| \DescribeMacro{\capitalizewords} turns % the first character of every word in {\it string} into its upper % case, if it is alphabetic. % Otherwise, that character will remain unaltered. For the purposes of % this command, ``the first character of a word'' is defined as either % the first character of the string, or the first non-blank % character that follows one or more blankspaces. % Default mode is |[v]|. % % The command |\capitalizetitle| \DescribeMacro{\capitalizetitle} is a % command similar to |\capitalizewords|, except that words which have % been previously designated as ``lower-case words'' are not % capitalized (\eg prepositions, conjunctions, \etc). In all cases, % the first word of the string is % capitalized, even if it is on the lower-case word list. Words are % added to the lower-case word list with the commands % |\addlcword|\DescribeMacro{\addlcword}, in the case of a single word, % or with |\addlcwords|\DescribeMacro{\addlcwords}, in the case of % multiple (space-separated) words. Because the addition of many words % to the lower-case list can substantially slow-down the execution of % the |\capitalizetitle| command, the command % |\resetlcwords| \DescribeMacro{\resetlcwords} has been added to % allow the user to zero out the lower-case word list. % (See newer \textsf{titlecaps} package as an alternative to this % command.) % % The command |\reversestring| \DescribeMacro{\reversestring} reverses % the sequence of characters in a string, such that what started as % the first character becomes the last character in the manipulated % string, and what started as the last character becomes the % first character. % Default mode is |[v]|. % % The command |\convertchar| \DescribeMacro{\convertchar} is a substitution % command in which a specified match character in the original string % ({\it from-char}) is substituted with a different string ({\it % to-string}). All occurances of {\it from-char} in the original % string are replaced. The {\it from-char} can only be a single % character (or tokenized symbol), whereas {\it to-string} can range % from the null-string (\ie character removal) to a single character % (\ie character substitution) % to a complete multi-character string. % Default mode is |[v]|. % % The command |\convertword| \DescribeMacro{\convertword} is a substitution % command in which a specified match string in the original string % ({\it from-string}) is substituted with a different string ({\it % to-string}). All occurances of {\it from-string} in the original % string are replaced. If {\it from-string} includes spaces, use % hard-space |(~)| characters instead of blanks. % Default mode is |[v]|. % % The command |\rotateword| \DescribeMacro{\rotateword} takes the first % word of {\it string} (and its leading and trailing spaces) % and rotates them to the end of the string. % Care must be taken to have a blankspace at the beginning or end % of {\it string} if one wishes to retain a blankspace word % separator between the original last word of the string and the % original first word which has been rotated to the end of the string. % Default mode is |[v]|. % % The command |\removeword| \DescribeMacro{\removeword} removes the % first word of {\it string}, along with any of its leading and trailing % spaces. % Default mode is |[v]|. % % The command |\getnextword| \DescribeMacro{\getnextword} returns the % next word of {\it string}. In this case, ``word'' is a sequence of % characters delimited either by spaces or by the beginning or end % of the string. % Default mode is |[v]|. % % The command |\getaword| \DescribeMacro{\getaword} returns a % word of {\it string} defined by the index, {\it n}. % In this case, ``word'' is a sequence of % characters delimited either by spaces or by the first or last % characters of the string. If the index, {\it n}, requested exceeds the % number of words available in the string, the index wraps around back % to the first argument of the string, such that asking for the tenth word % of an eight word string will return the second word of the string. % Default mode is |[v]|. % % The command |\rotateleadingspaces| % \DescribeMacro{\rotateleadingspaces} takes any leading spaces of the % string and rotates them to the end of the string. % Default mode is |[v]|. % % The command |\removeleadingspaces| % \DescribeMacro{\removeleadingspaces} removes any leading spaces of the % string. % Default mode is |[v]|. % % The command |\stringencode| \DescribeMacro{\stringencode} returns a % copy of the string that has been encoded according to the % \stringstrings encoding scheme. Because an encoded string is an % intermediate result, the default mode for this command is |[e]|. % % The command |\stringdecode| \DescribeMacro{\stringdecode} returns a % copy of the string that has been decoded. % Default mode is |[v]|. % % The command |\gobblechar| \DescribeMacro{\gobblechar} returns a string % in which the first character of {\it string} has been removed. Unlike % the \LaTeX{} system command |\@gobble| which removes the next {\bf % byte} in % the input stream, |\gobblechar| not only takes an argument as the % target of its gobble, but also removes one {\bf character}, regardless % of whether that character is a single-byte or multi-byte character. % Because this command may have utility outside of the \stringstrings % environment, the result of this command is retokenized (\ie |def|'ed) % rather than expanded (\ie |edef|'ed). % Default mode is |[q]|. Mode |[e]| is not recognized. % % The command |\gobblechars| \DescribeMacro{\gobblechars} returns a string % in which the first {\it n} characters of {\it string} have been removed. % Like |\gobblechar|, |\gobblechars| removes characters, regardless % of whether those characters are single-byte or multi-byte characters. % Likewise, the result of this command is retokenized (\ie |def|'ed) % rather than expanded (\ie |edef|'ed). % Default mode is |[q]|. Mode |[e]| is not recognized. % % The command |\retokenize| \DescribeMacro{\retokenize} takes a string % that is encoded according to the \stringstrings encoding scheme, and % repopulates the encoded characters with their \LaTeX{} tokens. This % command is particularly useful for exporting a string to a routine % outside of the \stringstrings library or if the string includes % the following % characters: |\{|, |\}|, \verb,\|,, |\dag|, |\ddag|, |\d|, |\t|, |\b|, % |\copyright|, and |\P|. % Default mode is |[q]|. Mode |[e]| is not recognized. % % \section {Commands to Extract String Information} % % These commands % take an input string or token, and ascertain a particular % characteristic of the string. They include: % % \noindent|\stringlength[|{\it mode}|]{|{\it string}|}|\\ % |\findchars[|{\it mode}|]{|{\it string}|}{|{\it match-char}|}|\\ % |\findwords[|{\it mode}|]{|{\it string}|}{|{\it match-string}|}|\\ % |\whereischar[|{\it mode}|]{|{\it string}|}{|{\it match-char}|}|\\ % |\whereisword[|{\it mode}|]{|{\it string}|}{|{\it match-string}|}|\\ % |\wordcount[|{\it mode}|]{|{\it string}|}|\\ % |\getargs[|{\it mode}|]{|{\it string}|}| % % \noindent Commands in this section return their result in the string % |\theresult|, unless otherwise specified. % Unless otherwise noted, the {\it mode} may take one of two values: % |[v]| for verbose mode (generally, the default), and |[q]| for quiet % mode. In both cases, the result of % the operation is stored in |\theresult|. In verbose mode, it is also % output immediately (and may be captured by an |\edef|). In quiet mode, % no string is output, though the result still resides in |\theresult|. % % The command |\stringlength| \DescribeMacro{\stringlength} returns the % length of {\it string} in characters (not bytes). % Default mode is |[v]|. % % The command |\findchars| \DescribeMacro{\findchars} checks to see if % the character {\it match-char} occurs anywhere in {\it string}. The % number of occurances is stored in |\theresult| and, if in verbose % mode, printed. If it is desired to find blankspaces, {\it match-char} % should be set to |{~}| and not |{ }|. % Default mode is |[v]|. % % The command |\findwords| \DescribeMacro{\findwords} checks to see if % the string {\it match-string} occurs anywhere in {\it string}. The % number of occurances is stored in |\theresult| and, if in verbose % mode, printed. If it is desired to find blankspaces, those % characters in {\it match-string} % should be set to hardspaces (\ie tildes) and not softspaces (\ie % blanks), regardless of how they are defined in {\it string}. % Default mode is |[v]|. % % The command |\whereischar| \DescribeMacro{\whereischar} checks to see % where % the character {\it match-char} first occurs in {\it string}. The % location of that occurance is stored in |\theresult| and, if in verbose % mode, printed. If the character is not found, |\theresult| is set to % a value of 0. If it is desired to find blankspaces, {\it match-char} % should be set to |{~}| and not |{ }|. % Default mode is |[v]|. % % The command |\whereisword| \DescribeMacro{\whereisword} checks to see % where % the string {\it match-string} first occurs in {\it string}. The % location of that occurance is stored in |\theresult| and, if in verbose % mode, printed. If {\it match-string} is not found, |\theresult| is set to % a value of 0. If it is desired to find blankspaces, those characters % in {\it match-string} % should be set to hardspaces (\ie tildes) and not softspaces (\ie % blanks), regardless of how they are defined in {\it string}. % Default mode is |[v]|. % % The command |\wordcount| \DescribeMacro{\wordcount} counts the number % of space-separated words that occur in {\it string}. % Default mode is |[v]|. % % The command |\getargs| \DescribeMacro{\getargs} mimics the Unix % command of the same name, in that it parses {\it string} to determine % how many arguments (\ie words) are in {\it string}, and extracts % each word into a separate variable. The number of arguments is placed % in |\narg| and the individual arguments are placed in variables of % the name |\argi|, |\argii|, |\argiii|, |\argiv|, etc. This command % may be used to facilitate simply the use of multiple optional % arguments in a \LaTeX{} command, for example % |\mycommand[|{\it option1 option2 option3}|]{|{\it argument}|}|. % In this case, % |\mycommand| should exercise |\getargs{#1}|, with the result being % that {\it option1} is stored in |\argi|, \etc~The command |\mycommand| % may then proceed to parse the optional arguments and branch % accordingly. % Default mode is |[q]|; |[e]| mode is permitted, while |[v]| mode % is disabled. % % \section {Commands to Test Strings} % % These commands take an input % string or token and test for a particular alphanumeric condition. % They include: % % \noindent% % |\isnextbyte[|{\it mode}|]{|{\it match-byte}|}{|{\it string}|}|\\ % |\testmatchingchar{|{\it % string}|}{|{\it n}|}{|{\it match-char}|}|\\ % |\testcapitalized{|{\it string}|}|\\ % |\testuncapitalized{|{\it string}|}|\\ % |\testleadingalpha{|{\it string}|}|\\ % |\testuppercase{|{\it string}|}|\\ % |\testsolelyuppercase{|{\it string}|}|\\ % |\testlowercase{|{\it string}|}|\\ % |\testsolelylowercase{|{\it string}|}|\\ % |\testalphabetic{|{\it string}|}| % % The command |\isnextbyte| \DescribeMacro{\isnextbyte} tests to see if % the first byte of {\it string} equals {\it match-byte}. It % is the only string-testing command in % this section which does not use the {\sf ifthen} test structure for % its result. Rather, |\isnextbyte| returns the result of its test as % a |T| or |F| in the string |\theresult|. More importantly, and % unlike other \stringstrings commands, |\isnextbyte| is a {\it byte} test % and not a {\it character} test. This means that, while |\isnextbyte| % operates very efficiently, it cannot % be used to directly detect multi-byte characters like |\$|, % |\^|, |\{|, |\}|, |\_|, |\dag|, |\ddag|, |\AE|, |\ae|, |\OE|, % |\oe|, \etc~(|\isnextbyte| will give false positives or negatives % when testing for these multi-byte characters). % The default mode of |\isnextbyte| is |[v]|. % % If a character needs to be tested, rather than a byte, % \DescribeMacro{\testmatchingchar} |\testmatchingchar| should be used. % The command |\testmatchingchar| is % used to ascertain whether character {\it n} of {\it string} equals % {\it match-char} or not. Whereas |\isnextbyte| checks only a {\it % byte}, |\testmatchingchar| tests for a {\it character} (single- or % multi-byte character). After the test is called, the action(s) may be % called out with |\ifmatchingchar| {\it true-code} |\else| {\it % false-code} |\fi|. % % The command |\testcapitalized| \DescribeMacro{\testcapitalized} is % used to ascertain whether the first character of {\it string} is % capitalized or not. If the first character is non-alphabetic, the % test will return FALSE. After the test is called, the action(s) may be % called out with |\ifcapitalized| {\it true-code} |\else| {\it % false-code} |\fi|. % % The command |\testuncapitalized| \DescribeMacro{\testuncapitalized} is % used to ascertain whether the first character of {\it string} is % uncapitalized. If the first character is non-alphabetic, the % test will return FALSE. After the test is called, the action(s) may be % called out with |\ifuncapitalized| {\it true-code} |\else| {\it % false-code} |\fi|. % % The command |\testleadingalpha| \DescribeMacro{\testleadingalpha} is % used to ascertain whether the first character of {\it string} is % alphabetic. After the test is called, the action(s) may be % called out with |\ifleadingalpha| {\it true-code} |\else| {\it % false-code} |\fi|. % % The command |\testuppercase| \DescribeMacro{\testuppercase} is % used to ascertain whether all the alphabetic characters in {\it % string} are uppercase or not. The presence of non-alphabetic % characters in {\it string} does not falsify the test, % but are merely ignored. However, a string completely void of % alphabetic characters will always test FALSE. % After the test is called, the action(s) may be % called out with |\ifuppercase| {\it true-code} |\else| {\it % false-code} |\fi|. % % The command |\testsolelyuppercase| % \DescribeMacro{\testsolelyuppercase} is % used to ascertain whether {\it all} the characters in {\it % string} are uppercase or not. The presence of non-alphabetic % characters in {\it string} other than blankspaces will automatically % falsify the test. Blankspaces are ignored. However, a null string or % a string composed solely of blankspaces will also test FALSE. % After the test is called, the action(s) may be % called out with |\ifsolelyuppercase| {\it true-code} |\else| {\it % false-code} |\fi|. % % The command |\testlowercase| \DescribeMacro{\testlowercase} is % used to ascertain whether all the alphabetic characters in {\it % string} are lowercase or not. The presence of non-alphabetic % characters in {\it string} does not falsify the test, % but are merely ignored. However, a string completely void of % alphabetic characters will always test FALSE. % After the test is called, the action(s) may be % called out with |\iflowercase| {\it true-code} |\else| {\it % false-code} |\fi|. % % The command |\testsolelylowercase| % \DescribeMacro{\testsolelylowercase} is % used to ascertain whether {\it all} the characters in {\it % string} are lowercase or not. The presence of non-alphabetic % characters in {\it string} other than blankspaces will automatically % falsify the test. Blankspaces are ignored. However, a null string or % a string composed solely of blankspaces will also test FALSE. % After the test is called, the action(s) may be % called out with |\ifsolelylowercase| {\it true-code} |\else| {\it % false-code} |\fi|. % % The command |\testalphabetic| % \DescribeMacro{\testalphabetic} is % used to ascertain whether {\it all} the characters in {\it % string} are alphabetic or not. The presence of non-alphabetic % characters in {\it string} other than blankspaces will automatically % falsify the test. Blankspaces are ignored. However, a null string or % a string composed solely of blankspaces will also test FALSE. % After the test is called, the action(s) may be % called out with |\ifalphabetic| {\it true-code} |\else| {\it % false-code} |\fi|. % % \section{Disclaimers} % % Now that we have described the commands available in the % \stringstrings package, it is appropriate to lay out the quirks and % warnings associated with the use of the package. % % First, \stringstrings is currently set to handle a string no larger % than 500 characters. A user could circumvent this, presumably, by % editing the style package to increase the value of % |\@MAXSTRINGSIZE| \DescribeMacro{\@MAXSTRINGSIZE}. % % It is important to remember that \stringstrings follows the underlying % rules of \LaTeX{}. Therefore, a passed string could not contain a raw % |%| as part of it, because it would, in fact, comment out the % remainder of the line. Naturally, the string may freely contain % instances of |\%|. % % Tokens that take two or more characters to express % (\eg |\#|, |\oe|, |\ddag|, \etc) are {\bf counted as % a single character} within the string. % The rule applies if you wanted to know the length % of a string that was populated with such tokens, or wanted to extract % a substring from a such a string. Of course, the exception that makes % the rule is that of diacritical marks, which count as separate symbols % from the characters they mark. For example, % |\^a| counts as two characters, because the |a| is % really just the operand of the |\^| token, even though the net result % looks like a single character (\^a). % % Consistent with % \LaTeX{} convention, groups of spaces are treated as a single % blankspace, unless encoded with |~| characters. And finally, again % consistent with the way \LaTeX{} operates, the space % that follows an alphabetic token is not actually a space in the % string, but serves as the delimiter to the token. Therefore, % |\OE dipus| (\OE dipus) has a length of six characters, % one for the |\OE| and five % for the |dipus|. The intervening space merely closes out the |\OE| % token, and does not represent a space in the middle of the string. % % One quirk worthy of particular note concerns the tabbing character, % meaning \& % as opposed to |\&| (which is handled without problem). % As of version 1.01, \stringstrings has the % capability to operate on arguments containg the ampersand \&, % normally reserved as the \LaTeX{} tabbing character. However, one % adverse by-product is that \& characters returned in |\thestring| % lose their catcode-4 value, and thus lose their ability to function as % tabbing characters. In the following example,\\ % | |\\ % | \caseupper[q]{a & b & c & d}|\\ % | \begin{tabular}{|\verb,|l|c|c|c|,|}|\\ % | \hline|\\ % | \thestring\\|\\ % | \hline|\\ % | \end{tabular}|\\ % | |\\ % will produce \caseupper[q]{a & b & c & d} % \begin{tabular}{\modetablelayout} % \hline % \thestring\\ % \hline % \end{tabular} % instead of the desired % \begin{tabular}{\modetablelayout} % \hline % A & B & C & D\\ % \hline % \end{tabular} % . % % In the |\substring| command, no tests are performed to guarantee that % the lower limit, {\it min}, is less than the upper limit, {\it max}, % or that {\it min} is even positive. However, the upper limit, % {\it max}, is corrected, if set larger than the string length. Also, % the use of the `\$' symbol to signify the last character of the string % and `\$--{\it n}' to denote an offset of {\it n} characters from the % end of the string can be helpful in avoiding the misindexing of strings. % % \begin{table}[p] % \caption{\bf Problematic Characters/Tokens and \stringstrings Solutions% % \label{tbl:prob}}\vspace{.5em} % \small % \begin{tabular}{\mylayout} % \LaTeX{} & Symbol/Name & Problem/Solution\\ % \hline % \hline % |{| & begin group & Cannot use |{| and |}| in \stringstrings % arguments.\\ % |}| & end group & However, use |\LB|\ldots|\RB| in lieu of |{|\ldots|}|;\\ % & & manipulate string in |[e]| mode \& |\retokenize| \\ % \hline % |\dag| & \dag~~Dagger & Cannot |\edef| these tokens; Thus, |[v]| mode\\ % |\ddag| & \ddag~~Double Dagger & fails with both OT1 and T1 encoding; \\ % |\P| & \P~~Pilcrow & manipulate string in |[e]| mode \& |\retokenize| \\ % |\d| & \d x~~Underdot & \\ % |\t| & \t xx~~Joining Arch & \\ % |\b| & \b x~~Letter Underline & \\ % |\copyright| & \copyright~Copyright & \\ % \hline % \hline % |\_| & \_~~Underscore & Cannot |\edef| with OT1 encoding; either\\ % |\{| & \{~~Left Curly Brace & |\renewcommand\encodingdefault{T1}|, or \\ % |\}| & \}~~Right Curly Brace & % manipulate string in |[e]| mode \& |\retokenize|. \\ % |\S| & \S~~Section Symbol & With OT1, |\S|, |\c| and |\pounds| break\\ % |\c| & \c x~~Cedilla & \stringstrings |[v]| mode.\\ % |\pounds| & \pounds~~Pounds & \\ % \hline % \verb,\|,& \stringstrings Pipe Char. & Distinct from \verb,|,, % the \stringstrings encoded-\\ % & \verb,|, (T1) ~~~\stringdecode{\|} (OT1) & escape character\\ % \hline % \hline % |\$| & \$~~Dollar & Either cannot |\edef|, or\\ % |\carat| & \mycarat~~(text mode) & % cannot identify uniquely with |\if| construct, or \\ % |\^| & \^x~~Circumflex & expanded character is more than one byte. \\ % |\'| & \'x~~Acute & \\ % |\"| & \"x~~Umlaut & {\it However},\\ % |\~| & \~x~~Tilde & % Use these characters freely, \stringstrings\\ % |\`| & \`x~~Grave & % encoding functions transparently with them.\\ % |\.| & \.x~~Overdot & \\ % |\=| & \=x~~Macron & |\retokenize| also works\\ % |\u| & \u x~~Breve & \\ % |\v| & \v x~~Caron & \\ % |\H| & \H x~~Double Acute & \\ % |\ss| & \ss~~Eszett & \\ % |\AE \ae| & \AE~\ae~~\ae sc & \\ % |\OE \oe| & \OE~\oe~~\oe thel & \\ % |\AA \aa| & \AA~\aa~~angstrom & \\ % |\O \o| & \O~\o~~slashed O & \\ % |\L \l| & \L~\l~~barred L & \\ % |~| & Hardspace &\\ % \hline % |$| & begin/end math mode & These characters pose no difficulties;\\ % |^| & math superscript & However, cannot extract substring that \\ % |_| & math subscript & breaks in middle of math mode.\\ % & & Other math mode symbols NOT supported.\\ % \hline % \& & ampersand & Version 1.01 \stringstrings can manipulate the\\ % & & ampersand. However, returned strings\\ % & & containing the \& character lose their\\ % & & catcode-4 status, making them unfit\\ % & & for use as tabbing characters.\\ % \hline % \hline % \end{tabular} % \end{table} % Table~\ref{tbl:prob} shows a variety of characters and tokens, some of % which pose a challenge to \stringstrings manipulations. In all cases, % a solution or workaround is provided. For symbols in the top two % categories, the workaround % solution includes the use of retokenized strings instead of expanded % strings. For symbols in the next two categories, use of T1 encoding % or retokenizing provides a satisfactory solution. In the bottom three % categories, because of \stringstrings encoded |[e]| mode, % there is nothing to impede the use of these characters in % \stringstrings arguments, if encoded |[e]| mode is employed for % intermediate calculations. Some of the % details of these problematic cases is described below. % % Not surprisingly, you are not allowed to extract a substring of a % string, if it breaks in the middle of math mode, because a substring % with only one |$| in it cannot be |\edef|'ed. % % There are a few potential quirks when using \LaTeX{}'s native OT1 % character encoding, most of which can be circumvented by using the % more modern % T1 encoding (accessed via |\renewcommand\encodingdefault{T1}| in the % document preamble). The quirks arise because there are % several characters that, while displayable in \LaTeX{}, are not part % of the OT1 character encoding. The characters include |\{|, |\}|, and % the \verb,|, symbol (accessed in \stringstrings via \verb,\|,). % When using \stringstrings to manipulate strings containing % these characters in the presence of OT1 encoding, % they come out looking like \stringdecode{\{}, \stringdecode{\}}, % and \stringdecode{\|}, respectively. However, if the T1 encoding fix % is not an option for you, you can also work around this problem by % |\retokenize|'ing the affected string (the |\retokenize| command is % provided to convert encoded, expanded strings back into tokenized % form, if need be). % % Likewise, for both OT1 and T1 encoding, the characters \dag~(|\dag|), % \ddag~(|\ddag|), \P~(|\P|), \d~~(|\d|), \t~~~(|\t|), \b~~~(|\b|), % and \copyright~(|\copyright|) % cannot be in the argument of an |\edef| expression. For % manipulated strings including these characters, |\retokenize| is the % only option available to retain the integrity of the string. % % As discussed thoroughly in the previous section, an ``encoded'' form of % the string manipulation routines is provided to prevent the % undesirable circumstance of passing an |\edef|'ed symbol as input % to a subsequent manipulation. Likewise, never try to ``decode'' % an already ``decoded'' string. % % When \stringstrings doesn't understand a token, it is supposed to % replace it with a period. However, some undecipherable characters may % inadvertantly be replaced with a space, instead. Of course, neither % of these possibilities is any comfort to the user. % % As mentioned already, \stringstrings cannot handle curly braces that % are used for grouping purposes, a circumstance which often arises in % math mode. Nonetheless, |\LB| and |\RB| may be used within % \stringstrings arguments in lieu of grouping braces, {\it if the final % result is to be retokenized}. Thus, |\caselower[e]{$X^\LB Y + Z\RB$}| % followed by |\convertchar[e]{\thestring}{x}{(1+x)}|, when finished up % with the following command, % |\retokenize[v]{\thestring}| yields as its result:\\ % \caselower[e]{$X^\LB Y + Z\RB$}\convertchar[e]{\thestring}{x}{(1+x)} % \retokenize[v]{\thestring}. % % One might ask, ``why not retokenize everything, instead of using the % |[v]| mode of the \stringstrings routines?'' While one {\it could} % do this, the answer is simply % that |\retokenize| is a computationally intensive command, and that % it is best used, therefore, only when the more efficient methods % will not suffice. In many, if not most cases, strings to be % manipulated will be solely composed of alphanumeric characters which % don't require the use of |\retokenize|, T1 encoding, or even % \stringstrings encoding. % % Despite these several disclaimers and workarounds required when % dealing with problematic characters, I hope you find the \stringstrings % architecture and feel to be straightforward and useful. There is only % one thing left, and that is to dissect the code\ldots and so here we % go. % %% \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 \~} % \StopEventually{} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \vspace{-0.8em} % \begin{macro}{stringstrings.sty} % \section{Code Listing} % I'll try to lay out herein % the workings of the \stringstrings style package. % \begin{macrocode} %<*package> %%%%% INITIALIZATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \catcode`\&=12 % \end{macrocode} % \end{macro} % % \begin{macro}{ifthen} % This package makes wide use of the {\sf ifthen} style package. % \begin{macrocode} \usepackage{ifthen} % \end{macrocode} % \end{macro} % \begin{macro}{\@MAXSTRINGSIZE} % The parameter |\@MAXSTRINGSIZE| defines the maximum allowable string % size that \stringstrings can operate upon. % \begin{macrocode} \def\@MAXSTRINGSIZE{500} % \end{macrocode} % \end{macro} % \begin{macrocode} \def\endofstring{@E@o@S@}% \def\undecipherable{.}% UNDECIPHERABLE TOKENS TO BE REPLACED BY PERIOD \def\@blankaction{\BlankSpace} % \end{macrocode} % Save the symbols which will get redefined \stringstrings encoding. % \begin{macrocode} \let\SaveDollar\$ \let\SaveHardspace~ \let\SaveCircumflex\^ \let\SaveTilde\~ \let\SaveUmlaut\" \let\SaveGrave\` \let\SaveAcute\' \let\SaveMacron\= \let\SaveOverdot\. \let\SaveBreve\u \let\SaveCaron\v \let\SaveDoubleAcute\H \let\SaveCedilla\c \let\SaveUnderdot\d \let\SaveArchJoin\t \let\SaveLineUnder\b \let\SaveCopyright\copyright \let\SavePounds\pounds \let\SaveLeftBrace\{ \let\SaveRightBrace\} \let\SaveUnderscore\_ \let\SaveDagger\dag \let\SaveDoubleDagger\ddag \let\SaveSectionSymbol\S \let\SavePilcrow\P \let\SaveAEsc\AE \let\Saveaesc\ae \let\SaveOEthel\OE \let\Saveoethel\oe \let\SaveAngstrom\AA \let\Saveangstrom\aa \let\SaveSlashedO\O \let\SaveSlashedo\o \let\SaveBarredL\L \let\SaveBarredl\l \let\SaveEszett\ss \let\SaveLB{ \let\SaveRB} % \end{macrocode} % The BlankSpace character is the only character which is reencoded % with a 1-byte re-encoding\ldots in this case the \OE~character. % \begin{macrocode} \def\EncodedBlankSpace{\SaveOEthel} \edef\BlankSpace{ } % \end{macrocode} % All other reencoded symbols consist of 2 bytes: an escape character % plus a unique code. The escape character is a pipe symbol. the % unique code comprises either a single number, letter, or symbol. % \begin{macrocode} \def\EscapeChar{|} % |0 IS AN ENCODED |, ACCESSED VIA \| \def\PipeCode{0} \def\EncodedPipe{\EscapeChar\PipeCode} \def\Pipe{|} \let\|\EncodedPipe % |1 IS AN ENCODED \$ \def\DollarCode{1} \def\EncodedDollar{\EscapeChar\DollarCode} % THE FOLLOWING IS NEEDED TO KEEP OT1 ENCODING FROM BREAKING; % IT PROVIDES AN ADEQUATE BUT NOT IDEAL ENVIRONMENT FOR T1 ENCODING \def\Dollar{\symbol{36}} % THE FOLLOWING IS BETTER FOR T1 ENCODING, BUT BREAKS OT1 ENCODING %\def\Dollar{\SaveDollar} % |W IS RESERVED TO BE ASSIGNED TO AN ARBITRARY TOKEN \def\UvariCode{W} \def\EncodedUvari{\EscapeChar\UvariCode} \def\Uvari{Uvari} \let\uvari\EncodedUvari % |X IS RESERVED TO BE ASSIGNED TO AN ARBITRARY TOKEN \def\UvariiCode{X} \def\EncodedUvarii{\EscapeChar\UvariiCode} \def\Uvarii{Uvarii} \let\uvarii\EncodedUvarii % |Y IS RESERVED TO BE ASSIGNED TO AN ARBITRARY TOKEN \def\UvariiiCode{Y} \def\EncodedUvariii{\EscapeChar\UvariiiCode} \def\Uvariii{Uvariii} \let\uvariii\EncodedUvariii % |2 IS AN ENCODED ^ FOR USE IN TEXT MODE, ACCESSED VIA \carat \def\CaratCode{2} \def\EncodedCarat{\EscapeChar\CaratCode} \def\Carat{\symbol{94}} \let\carat\EncodedCarat % |4 IS AN ENCODED \{ \def\LeftBraceCode{4} \def\EncodedLeftBrace{\EscapeChar\LeftBraceCode} % THE FOLLOWING IS NEEDED TO KEEP OT1 ENCODING FROM BREAKING; % IT PROVIDES AN ADEQUATE BUT NOT IDEAL ENVIRONMENT FOR T1 ENCODING \def\LeftBrace{\symbol{123}} % THE FOLLOWING IS BETTER FOR T1 ENCODING, BUT BREAKS OT1 ENCODING %\def\LeftBrace{\SaveLeftBrace} % |5 IS AN ENCODED \} \def\RightBraceCode{5} \def\EncodedRightBrace{\EscapeChar\RightBraceCode} % THE FOLLOWING IS NEEDED TO KEEP OT1 ENCODING FROM BREAKING; % IT PROVIDES AN ADEQUATE BUT NOT IDEAL ENVIRONMENT FOR T1 ENCODING \def\RightBrace{\symbol{125}} % THE FOLLOWING IS BETTER FOR T1 ENCODING, BUT BREAKS OT1 ENCODING %\def\RightBrace{\SaveRightBrace} % |6 IS AN ENCODED \_ \def\UnderscoreCode{6} \def\EncodedUnderscore{\EscapeChar\UnderscoreCode} \def\Underscore{\symbol{95}} %\def\Underscore{\SaveUnderscore} % |7 IS AN ENCODED \^ \def\CircumflexCode{7} \def\EncodedCircumflex{\EscapeChar\CircumflexCode} \def\Circumflex{\noexpand\SaveCircumflex} % |8 IS AN ENCODED \~ \def\TildeCode{8} \def\EncodedTilde{\EscapeChar\TildeCode} \def\Tilde{\noexpand\SaveTilde} % |" IS AN ENCODED \" \def\UmlautCode{"} \def\EncodedUmlaut{\EscapeChar\UmlautCode} \def\Umlaut{\noexpand\SaveUmlaut} % |` IS AN ENCODED \` \def\GraveCode{`} \def\EncodedGrave{\EscapeChar\GraveCode} \def\Grave{\noexpand\SaveGrave} % |' IS AN ENCODED \' \def\AcuteCode{'} \def\EncodedAcute{\EscapeChar\AcuteCode} \def\Acute{\noexpand\SaveAcute} % |= IS AN ENCODED \= \def\MacronCode{=} \def\EncodedMacron{\EscapeChar\MacronCode} \def\Macron{\noexpand\SaveMacron} % |. IS AN ENCODED \. \def\OverdotCode{.} \def\EncodedOverdot{\EscapeChar\OverdotCode} \def\Overdot{\noexpand\SaveOverdot} % |u IS AN ENCODED \u \def\BreveCode{u} \def\EncodedBreve{\EscapeChar\BreveCode} \def\Breve{\noexpand\SaveBreve} % |v IS AN ENCODED \v \def\CaronCode{v} \def\EncodedCaron{\EscapeChar\CaronCode} \def\Caron{\noexpand\SaveCaron} % |H IS AN ENCODED \H \def\DoubleAcuteCode{H} \def\EncodedDoubleAcute{\EscapeChar\DoubleAcuteCode} \def\DoubleAcute{\noexpand\SaveDoubleAcute} % |c IS AN ENCODED \c \def\CedillaCode{c} \def\EncodedCedilla{\EscapeChar\CedillaCode} \def\Cedilla{\noexpand\SaveCedilla} % |d IS AN ENCODED \d \def\UnderdotCode{d} \def\EncodedUnderdot{\EscapeChar\UnderdotCode} \def\Underdot{.}% CANNOT \edef \d % |t IS AN ENCODED \t \def\ArchJoinCode{t} \def\EncodedArchJoin{\EscapeChar\ArchJoinCode} \def\ArchJoin{.}% CANNOT \edef \t % |b IS AN ENCODED \b \def\LineUnderCode{b} \def\EncodedLineUnder{\EscapeChar\LineUnderCode} \def\LineUnder{.}% CANNOT \edef \b % |C IS AN ENCODED \copyright \def\CopyrightCode{C} \def\EncodedCopyright{\EscapeChar\CopyrightCode} \def\Copyright{.}% CANNOT \edef \copyright % |p IS AN ENCODED \pounds \def\PoundsCode{p} \def\EncodedPounds{\EscapeChar\PoundsCode} \def\Pounds{\SavePounds} % |[ IS AN ENCODED { \def\LBCode{[} \def\EncodedLB{\EscapeChar\LBCode} \def\UnencodedLB{.} \def\LB{\EncodedLB} % |] IS AN ENCODED } \def\RBCode{]} \def\EncodedRB{\EscapeChar\RBCode} \def\UnencodedRB{.} \def\RB{\EncodedRB} % |z IS AN ENCODED \dag \def\DaggerCode{z} \def\EncodedDagger{\EscapeChar\DaggerCode} \def\Dagger{.}% CANNOT \edef \dag % |Z IS AN ENCODED \ddag \def\DoubleDaggerCode{Z} \def\EncodedDoubleDagger{\EscapeChar\DoubleDaggerCode} \def\DoubleDagger{.}% CANNOT \edef \ddag % |S IS AN ENCODED \S \def\SectionSymbolCode{S} \def\EncodedSectionSymbol{\EscapeChar\SectionSymbolCode} \def\SectionSymbol{\SaveSectionSymbol} % |P IS AN ENCODED \P \def\PilcrowCode{P} \def\EncodedPilcrow{\EscapeChar\PilcrowCode} \def\Pilcrow{.}% CANNOT \edef \P % |E IS AN ENCODED \AE \def\AEscCode{E} \def\EncodedAEsc{\EscapeChar\AEscCode} \def\AEsc{\SaveAEsc} % |e IS AN ENCODED \ae \def\aescCode{e} \def\Encodedaesc{\EscapeChar\aescCode} \def\aesc{\Saveaesc} % |O IS AN ENCODED \OE \def\OEthelCode{O} \def\EncodedOEthel{\EscapeChar\OEthelCode} \def\OEthel{\SaveOEthel} % |o IS AN ENCODED \oe \def\oethelCode{o} \def\Encodedoethel{\EscapeChar\oethelCode} \def\oethel{\Saveoethel} % |A IS AN ENCODED \AA \def\AngstromCode{A} \def\EncodedAngstrom{\EscapeChar\AngstromCode} \def\Angstrom{\SaveAngstrom} % |a IS AN ENCODED \aa \def\angstromCode{a} \def\Encodedangstrom{\EscapeChar\angstromCode} \def\angstrom{\Saveangstrom} % |Q IS AN ENCODED \O \def\SlashedOCode{Q} \def\EncodedSlashedO{\EscapeChar\SlashedOCode} \def\SlashedO{\SaveSlashedO} % |q IS AN ENCODED \o \def\SlashedoCode{q} \def\EncodedSlashedo{\EscapeChar\SlashedoCode} \def\Slashedo{\SaveSlashedo} % |L IS AN ENCODED \L \def\BarredLCode{L} \def\EncodedBarredL{\EscapeChar\BarredLCode} \def\BarredL{\SaveBarredL} % |l IS AN ENCODED \l \def\BarredlCode{l} \def\EncodedBarredl{\EscapeChar\BarredlCode} \def\Barredl{\SaveBarredl} % |s IS AN ENCODED \ss \def\EszettCode{s} \def\EncodedEszett{\EscapeChar\EszettCode} \def\Eszett{\SaveEszett} \newcounter{@letterindex} \newcounter{@@letterindex} \newcounter{@@@letterindex} \newcounter{@wordindex} \newcounter{@iargc} \newcounter{@gobblesize} \newcounter{@maxrotation} \newcounter{@stringsize} \newcounter{@@stringsize} \newcounter{@@@stringsize} \newcounter{@revisedstringsize} \newcounter{@gobbleindex} \newcounter{@charsfound} \newcounter{@alph} \newcounter{@alphaindex} \newcounter{@capstrigger} \newcounter{@fromindex} \newcounter{@toindex} \newcounter{@previousindex} \newcounter{@flag} \newcounter{@matchloc} \newcounter{@matchend} \newcounter{@matchsize} \newcounter{@matchmax} \newcounter{@skipped} \newcounter{@lcwords} % \end{macrocode} % \begin{macrocode} %%%%% CONFIGURATION COMMANDS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \end{macrocode} % \begin{macro}{\defaultTreatments} % This command can be used to restore the default string treatments, % prior to calling |\substring|. The default treatments leave all % symbol types intact and unaltered. % \begin{macrocode} \newcommand\defaultTreatments{% \def\EncodingTreatment{v}% <--Set=v to decode special chars (vs. q,e) \def\AlphaCapsTreatment{1}% <--Set=1 to retain uppercase (vs. 0,2) \def\AlphaTreatment{1}% <--Set=1 to retain lowercase (vs. 0,2) \def\PunctuationTreatment{1}% <--Set=1 to retain punctuation (vs. 0) \def\NumeralTreatment{1}% <--Set=1 to retain numerals (vs. 0) \def\SymbolTreatment{1}% <--Set=1 to retain special chars (vs. 0) \def\BlankTreatment{1}% <--Set=1 to retain blanks (vs. 0) \def\CapitalizeString{0}% <--Set=0 for no special action (vs. 1,2) \def\SeekBlankSpace{0}% <--Set=0 for no special action (vs. 1,2) } \defaultTreatments % \end{macrocode} % \end{macro} % \begin{macro}{\Treatments} % This command allows the user to specify the desired character class % treatments, prior to a call to |\substring|. Unfortunately for the % user, I have specified which character class each symbol belongs to. % Therefore, it is not easy if the user decides that he wants a cedilla, % for example, to be treated like an alphabetic character rather than % a symbol. % \begin{macrocode} % QUICK WAY TO SET UP TREATMENTS BY WHICH \@rotate HANDLES VARIOUS % CHARACTERS \newcommand\Treatments[6]{% \def\AlphaCapsTreatment{#1}% <--Set=0 to remove uppercase % =1 to retain uppercase % =2 to change UC to lc \def\AlphaTreatment{#2}% <--Set=0 to remove lowercase % =1 to retain lowercase % =2 to change lc to UC \def\PunctuationTreatment{#3}%<--Set=0 to remove punctuation % =1 to retain punctuation \def\NumeralTreatment{#4}% <--Set=0 to remove numerals % =1 to retain numerals \def\SymbolTreatment{#5}% <--Set=0 to remove special chars % =1 to retain special chars \def\BlankTreatment{#6}% <--Set=0 to remove blanks % =1 to retain blanks } % \end{macrocode} % \end{macro} % \begin{macro}{\+} % This command (|\+|) is used to enact the \stringstrings encoding. % Key symbols are redefined, and any |\edef| which occurs while this % command is active will adopt these new definitions. % \begin{macrocode} % REENCODE MULTIBYTE SYMBOLS USING THE stringstrings ENCODING METHOD \newcommand\+{% \def\${\EncodedDollar}% \def~{\EncodedBlankSpace}% \def\^{\EncodedCircumflex}% \def\~{\EncodedTilde}% \def\"{\EncodedUmlaut}% \def\`{\EncodedGrave}% \def\'{\EncodedAcute}% \def\={\EncodedMacron}% \def\.{\EncodedOverdot}% \def\u{\EncodedBreve}% \def\v{\EncodedCaron}% \def\H{\EncodedDoubleAcute}% \def\c{\EncodedCedilla}% \def\d{\EncodedUnderdot}% \def\t{\EncodedArchJoin}% \def\b{\EncodedLineUnder}% \def\copyright{\EncodedCopyright}% \def\pounds{\EncodedPounds}% \def\{{\EncodedLeftBrace}% \def\}{\EncodedRightBrace}% \def\_{\EncodedUnderscore}% \def\dag{\EncodedDagger}% \def\ddag{\EncodedDoubleDagger}% \def\S{\EncodedSectionSymbol}% \def\P{\EncodedPilcrow}% \def\AE{\EncodedAEsc}% \def\ae{\Encodedaesc}% \def\OE{\EncodedOEthel}% \def\oe{\Encodedoethel}% \def\AA{\EncodedAngstrom}% \def\aa{\Encodedangstrom}% \def\O{\EncodedSlashedO}% \def\o{\EncodedSlashedo}% \def\L{\EncodedBarredL}% \def\l{\EncodedBarredl}% \def\ss{\EncodedEszett}% } % \end{macrocode} % \end{macro} % \begin{macro}{\?} % The command |\?| reverts the character encodings back to the standard % \LaTeX{} definitions. The command effectively undoes a previously % enacted |\+|. % \begin{macrocode} % WHEN TASK IS DONE, REVERT ENCODING TO STANDARD ENCODING METHOD \newcommand\?{% \let\$\SaveDollar% \let~\SaveHardspace% \let\^\SaveCircumflex% \let\~\SaveTilde% \let\"\SaveUmlaut% \let\`\SaveGrave% \let\'\SaveAcute% \let\=\SaveMacron% \let\.\SaveOverdot% \let\u\SaveBreve% \let\v\SaveCaron% \let\H\SaveDoubleAcute% \let\c\SaveCedilla% \let\d\SaveUnderdot% \let\t\SaveArchJoin% \let\b\SaveLineUnder% \let\copyright\SaveCopyright% \let\pounds\SavePounds% \let\{\SaveLeftBrace% \let\}\SaveRightBrace% \let\_\SaveUnderscore% \let\dag\SaveDagger% \let\ddag\SaveDoubleDagger% \let\S\SaveSectionSymbol% \let\P\SavePilcrow% \let\AE\SaveAEsc% \let\ae\Saveaesc% \let\OE\SaveOEthel% \let\oe\Saveoethel% \let\AA\SaveAngstrom% \let\aa\Saveangstrom% \let\O\SaveSlashedO% \let\o\SaveSlashedo% \let\L\SaveBarredL% \let\l\SaveBarredl% \let\ss\SaveEszett% } % \end{macrocode} % \end{macro} % \begin{macro}{\encodetoken} % The command |\encodetoken| assigns the supplied token to one of three % reserved \stringstrings user variables (the optional argument dictates % which user variable). Once encoded, the supplied token cannot be used % in the normal way, but only in stringstrings routines, unless and % until it is decoded. % \begin{macrocode} \newcommand\encodetoken[2][1]{% \if 1#1% \let\Uvari#2% \let#2\uvari\else \if 2#1% \let\Uvarii#2% \let#2\uvarii\else \if 3#1% \let\Uvariii#2% \let#2\uvariii% \fi \fi \fi } % \end{macrocode} % \end{macro} % \begin{macro}{\decodetoken} % The command |\decodetoken| deassigns the supplied token from the % reserved \stringstrings user variables (the optional argument dictates % which user variable), so that the token may be used in the normal way % again. % \begin{macrocode} \newcommand\decodetoken[2][1]{% \if 1#1% \let#2\Uvari% \def\Uvari{Uvari}\else \if 2#1% \let#2\Uvarii% \def\Uvarii{Uvarii}\else \if 3#1% \let#2\Uvariii% \def\Uvariii{Uvariii}% \fi \fi \fi } % \end{macrocode} % \end{macro} % \begin{macrocode} %%%%% COMMANDS TO MANIPULATE STRINGS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \end{macrocode} % In the next group of commands, the result is always stored in an % expandable string, |\thestring|. Expandable means that |\thestring| can % be put into a subsequent |\edef{}| command. Additionally, the % optional first argument can be used to cause three actions (verbose, % encoded, or quiet): % \begin{enumerate} % \item [|=v|] |\thestring| is decoded (final result); % print it immediately (default) % \item [|=e|] |\thestring| is encoded (intermediate result); % don't print it % \item [|=q|] |\thestring| is decoded (final result), % but don't print it % \end{enumerate} % \begin{macro}{\substring} % The command |\substring| is the brains of this package\ldots % It is used to acquire a substring from a given string, along with % performing specified character manipulations along the way. % Its strategy is fundamental to the \stringstrings % package: sequentially rotate the 1st character of the % string to the end of the string, until the desired substring resides % at end of rotated string. Then, gobble up the leading part of % string until only the desired substring is left. % \begin{macrocode} \newcommand\substring[4][v]{\+% % \end{macrocode} % Obtain the string length of the string to be manipulated and store % it in |@stringsize|. % \begin{macrocode} \@getstringlength{#2}{@stringsize}% % \end{macrocode} % First, % |\@decodepointer| is used to convert indirect references like |$| % and |$-3| into integers. % \begin{macrocode} \@decodepointer{#3}% \setcounter{@fromindex}{\@fromtoindex}% \@decodepointer{#4}% \setcounter{@toindex}{\@fromtoindex}% % \end{macrocode} % Determine the number of characters to rotate to the end of the string % and the number of characters to then gobble from it, in order to leave % the desired substring. % \begin{macrocode} \setcounter{@gobblesize}{\value{@stringsize}}% \ifthenelse{\value{@toindex} > \value{@stringsize}}% {\setcounter{@maxrotation}{\value{@stringsize}}}% {\setcounter{@maxrotation}{\value{@toindex}}}% \addtocounter{@gobblesize}{-\value{@maxrotation}}% \addtocounter{@gobblesize}{\value{@fromindex}}% \addtocounter{@gobblesize}{-1}% % \end{macrocode} % Prepare for the string rotation by initializing counters, setting the % targeted string into the working variable, |\rotatingword|, and set % the encoding treatment specified. % \begin{macrocode} \setcounter{@letterindex}{0}% \edef\rotatingword{#2}% \def\EncodingTreatment{#1}% % \end{macrocode} % If capitalization (first character of string or of each word) % was specified, the % trigger for 1st-character capitalization will be set. However, % the treatments for the alphabetic characters for the remainder of the % string must be saved and reinstituted after the first character is % capitalized. % \begin{macrocode} \if 0\CapitalizeString% % DO NOT SET CAPITALIZE TRIGGER FOR FIRST CHARACTER \setcounter{@capstrigger}{0}% \else % SAVE CERTAIN TREATMENTS FOR LATER RESTORATION \let\SaveAlphaTreatment\AlphaTreatment% \let\SaveAlphaCapsTreatment\AlphaCapsTreatment% % SET CAPITALIZE TRIGGER FOR FIRST CHARACTER \setcounter{@capstrigger}{1}% \@forcecapson% \fi % \end{macrocode} % The command |\@defineactions| looks at the defined treatments % and specifies how each of the \stringstrings encoded % characters should be handled (\ie left alone, removed, modified, % \etc). % \begin{macrocode} \@defineactions% % \end{macrocode} % Here begins the primary loop of |\substring| in which characters of % |\rotatingword| are successively moved (and possibly manipulated) % from the first character of the string to the last. |@letterindex| is % the running index defining how many characters have been operated on. % \begin{macrocode} \whiledo{\value{@letterindex} < \value{@maxrotation}}{% \addtocounter{@letterindex}{1}% % \end{macrocode} % When |\CapitalizeString| equals 1, only the first character of the % string is capitalized. When it equals 2, every word in the string % is capitalized. When equal to 2, this bit of code looks for the % blankspace that follows the end of a word, and uses it to reset the % capitalization trigger for the next non-blank character. % \begin{macrocode} % IF NEXT CHARACTER BLANK WHILE \CapitalizeString=2, % SET OR KEEP ALIVE TRIGGER. \if 2\CapitalizeString% \isnextbyte[q]{\EncodedBlankSpace}{\rotatingword}% \if F\theresult\isnextbyte[q]{\BlankSpace}{\rotatingword}\fi% \if T\theresult% \if 0\arabic{@capstrigger}% \@forcecapson% \@defineactions% \fi \setcounter{@capstrigger}{2}% \fi \fi % \end{macrocode} % Is the next character an encoded symbol? If it is a normal character, % simply rotate it to the end of the string. % If it is an encoded symbol however, its % treatment will depend on whether it will be gobbled away or end up % in the final substring. If it will be gobbled away, leave it encoded, % because the gobbling routine knows how to gobble encoded characters. % If it will end up in the substring, manipulate it according to the % encoding rules set in |\@defineactions| and rotate it. % \begin{macrocode} % CHECK IF NEXT CHARACTER IS A SYMBOL \isnextbyte[q]{\EscapeChar}{\rotatingword}% \ifthenelse{\value{@letterindex} < \value{@fromindex}}% {% % THIS CHARACTER WILL EVENTUALLY BE GOBBLED \if T\theresult% % ROTATE THE ESCAPE CHARACTER, WHICH WILL LEAVE THE SYMBOL ENCODED % FOR PROPER GOBBLING (ESCAPE CHARACTER DOESN'T COUNT AS A LETTER) \edef\rotatingword{\@rotate{\rotatingword}}% \addtocounter{@letterindex}{-1}% \else % NORMAL CHARACTER OR SYMBOL CODE... ROTATE IT \edef\rotatingword{\@rotate{\rotatingword}}% \fi }% {% % THIS CHARACTER WILL EVENTUALLY MAKE IT INTO SUBSTRING \if T\theresult% % ROTATE THE SYMBOL USING DEFINED TREATMENT RULES \edef\rotatingword{\ESCrotate{\expandafter\@gobble\rotatingword}}% \else % NORMAL CHARACTER... ROTATE IT \edef\rotatingword{\@rotate{\rotatingword}}% \fi }% % \end{macrocode} % Here, the capitalization trigger persistently tries to turn % itself off with each loop % through the string rotation. Only if the earlier code found the % rotation to be pointing to the blank character(s) between words while % |\CapitalizeString| equals 2 will the trigger be prevented from % extinguishing itself. % \begin{macrocode} % DECREMENT CAPITALIZATION TRIGGER TOWARDS 0, EVERY TIME THROUGH LOOP \if 0\arabic{@capstrigger}% \else \addtocounter{@capstrigger}{-1}% \if 0\arabic{@capstrigger}\@relaxcapson\fi \fi % \end{macrocode} % In addition to the standard |\substring| calls in which fixed % substring limits are specified (which in turn fixes the number of % character rotations to be executed), some \stringstrings commands % want the rotations to continue until a blankspace is located. % This bit of code looks for that blank space, if that was the option % requested. Once found, the rotation will stop. However, depending % on the value of |\SeekBlankSpace|, the remainder of the string may % either be retained or discarded. % \begin{macrocode} % IF SOUGHT SPACE IS FOUND, END ROTATION OF STRING \if 0\SeekBlankSpace\else \isnextbyte[q]{\EncodedBlankSpace}{\rotatingword}% \if F\theresult\isnextbyte[q]{\BlankSpace}{\rotatingword}\fi% \if T\theresult% \if 1\SeekBlankSpace% % STOP ROTATION, KEEP REMAINDER OF STRING \setcounter{@maxrotation}{\value{@letterindex}}% \else % STOP ROTATION, THROW AWAY REMAINDER OF STRING \addtocounter{@gobblesize}{\value{@maxrotation}}% \setcounter{@maxrotation}{\value{@letterindex}}% \addtocounter{@gobblesize}{-\value{@maxrotation}}% \fi \fi \fi }% % \end{macrocode} % The loop has ended.\\ % Gobble up the first |@gobblesize| characters (not bytes!)~of the string, % which should leave the desired substring as the remainder. If the % mode is verbose, print out the resulting substring. % \begin{macrocode} % GOBBLE AWAY THAT PART OF STRING THAT ISN'T PART OF REQUESTED SUBSTRING \@gobblearg{\rotatingword}{\arabic{@gobblesize}}% \edef\thestring{\gobbledword}% \if v#1\thestring\fi% \?} % \end{macrocode} % \end{macro} % Many of the following commands are self-expanatory. The recipe they % follow is to use |\Treatments| to specify how different character % classes are to be manipulated, and then to call upon |\substring| to % effect the desired manipulation. Treatments are typically % re-defaulted at the conclusion of the command, which is why the user, % if desiring special treatments, should specify those treatments % immediately before a call to |\substring|. % \begin{macro}{\caseupper} % \begin{macrocode} % Convert Lower to Uppercase; retain all symbols, numerals, % punctuation, and blanks. \newcommand\caseupper[2][v]{% \Treatments{1}{2}{1}{1}{1}{1}% \substring[#1]{#2}{1}{\@MAXSTRINGSIZE}% \defaultTreatments% } % \end{macrocode} % \end{macro} % \begin{macro}{\caselower} % \begin{macrocode} % Convert Upper to Lowercase; retain all symbols, numerals, % punctuation, and blanks. \newcommand\caselower[2][v]{% \Treatments{2}{1}{1}{1}{1}{1}% \substring[#1]{#2}{1}{\@MAXSTRINGSIZE}% \defaultTreatments% } % \end{macrocode} % \end{macro} % \begin{macro}{\solelyuppercase} % \begin{macrocode} % Convert Lower to Uppercase; discard symbols, numerals, and % punctuation, but keep blanks. \newcommand\solelyuppercase[2][v]{% \Treatments{1}{2}{0}{0}{0}{1}% \substring[#1]{#2}{1}{\@MAXSTRINGSIZE}% \defaultTreatments% } % \end{macrocode} % \end{macro} % \begin{macro}{\solelylowercase} % \begin{macrocode} % Convert Upper to Lowercase; discard symbols, numerals, and % punctuation, but keep blanks. \newcommand\solelylowercase[2][v]{% \Treatments{2}{1}{0}{0}{0}{1}% \substring[#1]{#2}{1}{\@MAXSTRINGSIZE}% \defaultTreatments% } % \end{macrocode} % \end{macro} % \begin{macro}{\changecase} % \begin{macrocode} % Convert Lower to Uppercase & Upper to Lower; retain all symbols, numerals, % punctuation, and blanks. \newcommand\changecase[2][v]{% \Treatments{2}{2}{1}{1}{1}{1}% \substring[#1]{#2}{1}{\@MAXSTRINGSIZE}% \defaultTreatments% } % \end{macrocode} % \end{macro} % \begin{macro}{\noblanks} % \begin{macrocode} % Remove blanks; retain all else. \newcommand\noblanks[2][v]{% \Treatments{1}{1}{1}{1}{1}{0}% \substring[#1]{#2}{1}{\@MAXSTRINGSIZE}% \defaultTreatments% } % \end{macrocode} % \end{macro} % \begin{macro}{\nosymbolsnumerals} % \begin{macrocode} % Retain case; discard symbols & numerals; retain % punctuation & blanks. \newcommand\nosymbolsnumerals[2][v]{% \Treatments{1}{1}{1}{0}{0}{1}% \substring[#1]{#2}{1}{\@MAXSTRINGSIZE}% \defaultTreatments% } % \end{macrocode} % \end{macro} % \begin{macro}{\alphabetic} % \begin{macrocode} % Retain case; discard symbols, numerals & % punctuation; retain blanks. \newcommand\alphabetic[2][v]{% \Treatments{1}{1}{0}{0}{0}{1}% \substring[#1]{#2}{1}{\@MAXSTRINGSIZE}% \defaultTreatments% } % \end{macrocode} % \end{macro} % \begin{macro}{\capitalize} % The command |\CapitalizeString| is not set by |\Treatments|, but % only in |\capitalize| or in |\capitalizewords|. % \begin{macrocode} % Capitalize first character of string, \newcommand\capitalize[2][v]{% \defaultTreatments% \def\CapitalizeString{1}% \substring[#1]{#2}{1}{\@MAXSTRINGSIZE}% \def\CapitalizeString{0}% } % \end{macrocode} % \end{macro} % \begin{macro}{\capitalizewords} % \begin{macrocode} % Capitalize first character of each word in string, \newcommand\capitalizewords[2][v]{% \defaultTreatments% \def\CapitalizeString{2}% \substring[#1]{#2}{1}{\@MAXSTRINGSIZE}% \def\CapitalizeString{0}% } % \end{macrocode} % \end{macro} % \begin{macro}{\reversestring} % Reverses a string from back to front. To do this, a loop is set % up in which characters are grabbed one at a time from the end of the % given string, working towards the beginning of the string. The % grabbed characters are concatenated onto the end of the working % string, |\@reversedstring|. By the time the loop is complete % |\@reversedstring| fully represents the reversed string. The result % is placed into |\thestring|. % \begin{macrocode} % REVERSES SEQUENCE OF CHARACTERS IN STRING \newcommand\reversestring[2][v]{% \def\@reversedstring{}% \+\@getstringlength{#2}{@@stringsize}\?% \setcounter{@@@letterindex}{\the@@stringsize}% \whiledo{\the@@@letterindex > 0}{% \if e#1% \substring[e]{#2}{\the@@@letterindex}{\the@@@letterindex}% \else \substring[q]{#2}{\the@@@letterindex}{\the@@@letterindex}% \fi \edef\@reversedstring{\@reversedstring\thestring}% \addtocounter{@@@letterindex}{-1}% }% \edef\thestring{\@reversedstring}% \if v#1\thestring\fi% } % \end{macrocode} % \end{macro} % \begin{macro}{\convertchar} % Takes a string, and replaces each occurance of a specified character % with a replacement string. The only complexity in the logic is that % a separate replacement algorithm exists depending on whether the % specified character to be replaced is a normal character or an % encoded character. % \begin{macrocode} % TAKES A STARTING STRING #2 AND SUBSTITUTES A SPECIFIED STRING #4 % FOR EVERY OCCURANCE OF A PARTICULAR GIVEN CHARACTER #3. THE % CHARACTER TO BE CONVERTED MAY BE EITHER A PLAIN CHARACTER OR % AN ENCODABLE SYMBOL. \newcommand\convertchar[4][v]{% \+% \edef\encodedstring{#2}% \edef\encodedfromarg{#3}% \edef\encodedtoarg{#4}% \?% \isnextbyte[q]{\EscapeChar}{\encodedfromarg}% \if F\theresult% % PLAIN "FROM" ARGUMENT \@convertbytetostring[#1]{\encodedstring}{#3}{\encodedtoarg}% \else % ENCODABLE "FROM" ARGUMENT \@convertsymboltostring[#1]{\encodedstring}% {\expandafter\@gobble\encodedfromarg}{\encodedtoarg}% \fi } % \end{macrocode} % \end{macro} % \begin{macro}{\convertword} % Takes a string, a replaces each occurance of a specified string % with a replacement string. % \begin{macrocode} \newcounter{@@matchloc} % LIKE \convertchar, EXCEPT FOR WORDS \newcommand\convertword[4][v]{% \+\edef\@@teststring{#2}% \edef\@fromstring{#3}% \edef\@tostring{#4}\?% \edef\@@@teststring{\@@teststring}% \def\@buildfront{}% \edef\@buildstring{\@@teststring}% \setcounter{@charsfound}{0}% \whiledo{\the@charsfound > -1}{% % \end{macrocode} % Seek occurance of |\@fromstring| in larger |\@@teststring| % \begin{macrocode} \whereisword[q]{\@@teststring}{\@fromstring}% \setcounter{@matchloc}{\theresult}% \ifthenelse{\the@matchloc = 0}% {% % \end{macrocode} % Not found. Done. % \begin{macrocode} \setcounter{@charsfound}{-1}% }% {% % \end{macrocode} % Potential matchstring. % \begin{macrocode} \addtocounter{@charsfound}{1}% % \end{macrocode} % Grab current test string from beginning to point just prior % to potential match. % \begin{macrocode} \addtocounter{@matchloc}{-1}% \substring[e]{\@@@teststring}{1}{\the@matchloc}% % \end{macrocode} % The string |\@buildfront| is the total original string, with % string substitutions, from character 1 to current potential match. % \begin{macrocode} \edef\@buildfront{\@buildfront\thestring}% % \end{macrocode} % See if potential matchstring takes us to end-of-string\ldots % \begin{macrocode} \addtocounter{@matchloc}{1}% \addtocounter{@matchloc}{\the@matchsize}% \ifthenelse{\the@matchloc > \the@@@stringsize}% {% % \end{macrocode} % \ldots if so, then match is last one in string. Tack on replacement % string to |\@buildfront| to create final string. Exit. % \begin{macrocode} \setcounter{@charsfound}{-1}% \edef\@buildstring{\@buildfront\@tostring}% }% {% % \end{macrocode} % \ldots if not, redefine current teststring to begin at point following % the current substitution. Make substitutions to current % |\@buildstring| and |\@buildfront|. Loop through logic again on new % teststring. % \begin{macrocode} \substring[e]{\@@@teststring}{\the@matchloc}{\@MAXSTRINGSIZE}% \edef\@@teststring{\thestring}% \edef\@@@teststring{\@@teststring}% \edef\@buildstring{\@buildfront\@tostring\@@@teststring}% \edef\@buildfront{\@buildfront\@tostring}% }% }% }% \substring[#1]{\@buildstring}{1}{\@MAXSTRINGSIZE}% } % \end{macrocode} % \end{macro} % \begin{macro}{\resetlcwords} % Removes all words from designated ``lower-case words'' list. This can % be useful because large lists of lower-case words can significantly % slow-down the function of |\capitalizetitle|. % \begin{macrocode} \setcounter{@lcwords}{0} % RESET LOWER-CASE WORD COUNT; START OVER \newcommand\resetlcwords[0]{% \setcounter{@lcwords}{0}% } % \end{macrocode} % \end{macro} % \begin{macro}{\addlcwords} % Add words to the list of designated ``lower-case words'' which will % not be capitalized by |\capitalizetitle|. The input should consist of % space-separated words, which are, in turn, passed on to |\addlcword|. % \begin{macrocode} % PROVIDE LIST OF SPACE-SEPARATED WORDS TO REMAIN LOWERCASE IN TITLES \newcommand\addlcwords[1]{% \getargs{#1}% \setcounter{@wordindex}{0}% \whiledo{\value{@wordindex} < \narg}{% \addtocounter{@wordindex}{1}% \addlcword{\csname arg\roman{@wordindex}\endcsname}% } } % \end{macrocode} % \end{macro} % \begin{macro}{\addlcword} % Add a word to the list of designated ``lower-case words'' which will % not be capitalized by |\capitalizetitle|. % \begin{macrocode} % PROVIDE A SINGLE WORD TO REMAIN LOWERCASE IN TITLES \newcommand\addlcword[1]{% \addtocounter{@lcwords}{1}% \expandafter\edef\csname lcword\roman{@lcwords}\endcsname{#1} } % \end{macrocode} % \end{macro} % \begin{macro}{\capitalizetitle} % Makes every word of a multi-word input string capitalized, except for % specifically noted ``lower-case words'' (examples might include % prepositions, conjunctions, \etc). The first word of the input string % is capitalized, while lower-case words, previously designated with % |\addlcword| and |\addlcwords|, are left in lower case. % \begin{macrocode} % CAPITALIZE TITLE, EXCEPT FOR DESIGNATED "LOWER-CASE" WORDS \newcommand\capitalizetitle[2][v]{% % First, capitalize every word (save in encoded form, not printed) \capitalizewords[e]{#2}% % Then lowercase words that shouldn't be capitalized, like articles, % prepositions, etc. (save in encoded form, not printed) \setcounter{@wordindex}{0}% \whiledo{\value{@wordindex} < \value{@lcwords}}{% \addtocounter{@wordindex}{1}% \edef\mystring{\thestring}% \edef\lcword{\csname lcword\roman{@wordindex}\endcsname}% \capitalize[e]{\lcword}% \edef\ucword{\thestring}% \convertword[e]{\mystring}{\ucword~}{\lcword~}% } % Finally, recapitalize the first word of the Title, and print it. \capitalize[#1]{\thestring}% } % \end{macrocode} % \end{macro} % \begin{macro}{\rotateword} % Moves first word of given string |#2| to end of string, including % leading and trailing blank spaces. % \begin{macrocode} \newcommand\rotateword[2][v]{% \+\edef\thestring{#2}\?% % \end{macrocode} % Rotate leading blank spaces to end of string % \begin{macrocode} \@treatleadingspaces[e]{\thestring}{}% % \end{macrocode} % Define end-of-rotate condition for |\substring| as next blank space % \begin{macrocode} \def\SeekBlankSpace{1}% % \end{macrocode} % Leave rotated characters alone % \begin{macrocode} \Treatments{1}{1}{1}{1}{1}{1}% % \end{macrocode} % Rotate to the next blank space or the end of string, whichever comes % first. % \begin{macrocode} \substring[e]{\thestring}{1}{\@MAXSTRINGSIZE}% % \end{macrocode} % Rotate trailing spaces. % \begin{macrocode} \@treatleadingspaces[#1]{\thestring}{}% \defaultTreatments% } % \end{macrocode} % \end{macro} % \begin{macro}{\removeword} % Remove the first word of given string |#2|, including leading and % trailing spaces. Note that logic is identical to |\rotateword|, % except that affected spaces and characters are removed instead of % being rotated. % \begin{macrocode} \newcommand\removeword[2][v]{% \+\edef\thestring{#2}\?% % \end{macrocode} % The |{x}| final argument indicates to delete leading spaces. % \begin{macrocode} \@treatleadingspaces[e]{\thestring}{x}% \def\SeekBlankSpace{1}% % \end{macrocode} % The Treatments are specified to remove all characters. % \begin{macrocode} \Treatments{0}{0}{0}{0}{0}{0}% \substring[e]{\thestring}{1}{\@MAXSTRINGSIZE}% % \end{macrocode} % Trailing spaces are also deleted. % \begin{macrocode} \@treatleadingspaces[#1]{\thestring}{x}% \defaultTreatments% } % \end{macrocode} % \end{macro} % \begin{macro}{\getnextword} % A special case of |\getaword|, where word-to-get is specified as % ``1''. % \begin{macrocode} % GETS NEXT WORD FROM STRING #2. % NOTE: ROTATES BACK TO BEGINNING, AFTER STRING OTHERWISE EXHAUSTED \newcommand\getnextword[2][v]{% \getaword[#1]{#2}{1}% } % \end{macrocode} % \end{macro} % \begin{macro}{\getaword} % Obtain a specified word number (|#3|) from string |#2|. Logic: rotate % leading spaces to end of string; then loop |#3|~--~1 times through % |\rotateword|. Finally, get next word. % \begin{macrocode} % GETS WORD #3 FROM STRING #2. % NOTE: ROTATES BACK TO BEGINNING, AFTER STRING OTHERWISE EXHAUSTED \newcommand\getaword[3][v]{% \setcounter{@wordindex}{1}% \+\edef\thestring{#2}\?% \@treatleadingspaces[e]{\thestring}{}% \whiledo{\value{@wordindex} < #3}{% \rotateword[e]{\thestring}% \addtocounter{@wordindex}{1}% }% \@getnextword[#1]{\thestring}% } % \end{macrocode} % \end{macro} % % \begin{macro}{\rotateleadingspaces} % Rotate leading spaces of string |#2| to the end of string. % \begin{macrocode} \newcommand\rotateleadingspaces[2][v]{% \@treatleadingspaces[#1]{#2}{}% } % \end{macrocode} % \end{macro} % \begin{macro}{\removeleadingspaces} % Remove leading spaces from string |#2|. % \begin{macrocode} \newcommand\removeleadingspaces[2][v]{% \@treatleadingspaces[#1]{#2}{x}% } % \end{macrocode} % \end{macro} % \begin{macro}{\stringencode} % \begin{macrocode} % ENCODE STRING; UNLIKE OTHER COMMANDS, DEFAULT IS NO PRINT \newcommand\stringencode[2][e]{% \defaultTreatments% \substring[#1]{#2}{1}{\@MAXSTRINGSIZE}% } % \end{macrocode} % \end{macro} % \begin{macro}{\stringdecode} % \begin{macrocode} % DECODE STRING \newcommand\stringdecode[2][v]{% \defaultTreatments% \substring[#1]{#2}{1}{\@MAXSTRINGSIZE}% } % \end{macrocode} % \end{macro} % \begin{macro}{\gobblechar} % Remove first character (not byte!) from string |#2|. Unlike just about % all other \stringstrings commands, result is retokenized and not % expanded. % \begin{macrocode} % SINGLE-CHARACTER VERSION OF \gobblechars. IN THIS CASE, TWO-BYTE % ESCAPE SEQUENCES, WHEN ENCOUNTERED, COUNT AS A SINGLE GOBBLE. \newcommand\gobblechar[2][q]{\+% \@gobblearg{#2}{1}% \?\retokenize[#1]{\gobbledword}% } % \end{macrocode} % \end{macro} % \begin{macro}{\gobblechars} % Remove first |#3| characters (not bytes!) from string |#2|. % Unlike just about all other \stringstrings commands, result is % retokenized and not expanded. % \begin{macrocode} % USER CALLABLE VERSION OF \@gobblearg. TURNS ON REENCODING. % GOBBLE FIRST #3 CHARACTERS FROM STRING #2. TWO-BYTE % ESCAPE SEQUENCES, WHEN ENCOUNTERED, COUNT AS A SINGLE GOBBLE. \newcommand\gobblechars[3][q]{\+% \@gobblearg{#2}{#3}% \?\retokenize[#1]{\gobbledword}% } % \end{macrocode} % \end{macro} % \begin{macro}{\retokenize} % One of the key \stringstrings routines that provides several % indispensible functions. Its function is to take an encoded string % |#2| that has been given, and repopulate the string with its \LaTeX{} % tokens in a |\def| form (not an expanded |\edef| form). It is % useful if required to operate on a string outside of the % \stringstrings library routines, following a \stringstrings % manipulation. It is also useful to display certain tokens which % cannot be manipulated in expanded form. See % Table~\ref{tbl:prob} for a list of tokens that will only work when the % resulting string is retokenized (and not expanded). % % Logic: Loop through each character of given string |#2|. Each % successive character of the string is retokenized as |\inexttoken|, % |\iinexttoken|, |\iiinexttoken|, |\ivnexttoken|, \etc, respectively. % Then a series of strings are formed as\\ % \\ % |\def\buildtoken{}|\\ % |\def\buildtokeni{\builtoken\inexttoken}|\\ % |\def\buildtokenii{\builtokeni\iinexttoken}|\\ % |\def\buildtokeniii{\builtokenii\iiinexttoken}|\\ % |\def\buildtokeniv{\builtokeniii\ivnexttoken}|\\ % \\ % The last in the sequence of |\builtoken...| strings (renamed % |\buildtokenq|) is the retokenized % version of string |#2|. % \begin{macrocode} % CONVERTS ENCODED STRING BACK INTO TOKENIZED FORM (i.e., def'ED). \newcommand\retokenize[2][q]{\+% \edef\@svstring{#2}% \edef\buildtoken{}% \@getstringlength{#2}{@@stringsize}\?% \setcounter{@@letterindex}{0}% \whiledo{\the@@letterindex < \the@@stringsize}{% \setcounter{@previousindex}{\the@@letterindex}% \addtocounter{@@letterindex}{1}% \substring[e]{\@svstring}{\the@@letterindex}{\the@@letterindex}% \@retokenizechar{\thestring}{\roman{@@letterindex}nexttoken}% \expandafter\def\csname buildtoken\roman{@@letterindex}% \expandafter\endcsname\expandafter% {\csname buildtoken\roman{@previousindex}\expandafter\endcsname% \csname\roman{@@letterindex}nexttoken\endcsname}% }% \expandafter\def\expandafter\buildtokenq\expandafter{% \csname buildtoken\roman{@@letterindex}\endcsname}% \def\thestring{\buildtokenq}% \if v#1\thestring\fi } % \end{macrocode} % \end{macro} % \begin{macrocode} % %%%%% COMMANDS TO EXTRACT STRING INFORMATION %%%%%%%%%%%%%%%%%%%%%%%%%% % \end{macrocode} % The following group of commands extract information about a string, % and store the result in a string called |\theresult|. Since the % result is not a substring, a \textit{mode} of |[e]| carries no % meaning. Only |[v]| and |[q]| modes apply here. % \begin{macro}{\stringlength} % Returns the length of the given string in \textit{characters}, not % \textit{bytes}. % \begin{macrocode} % USER CALLABLE VERSION of \@getstringlength: % GET'S STRING LENGTH OF [#2], PUTS RESULT IN \theresult. PRINTS RESULT % UNLESS IN QUIET [q] MODE. \newcommand\stringlength[2][v]{\+% \@getstringlength{#2}{@@stringsize}% \edef\theresult{\arabic{@@stringsize}}% \if v#1\theresult\fi% \?} % \end{macrocode} % \end{macro} % \begin{macro}{\findchars} % Find number of occurances of character |#3| in string |#2|. % \begin{macrocode} % CHECKS TO SEE IF THE CHARACTER [#3] APPEARS ANYWHERE IN STRING [#2]. % THE NUMBER OF OCCURANCES IS PRINTED OUT, EXCEPT WHEN [#1]=q, QUIET % MODE. RESULT IS ALSO STORED IN \theresult . TO FIND SPACES, ARG3 % SHOULD BE SET TO {~}, NOT { }. \newcommand\findchars[3][v]{\+% \@getstringlength{#2}{@@stringsize}% \setcounter{@charsfound}{0}% \setcounter{@@letterindex}{0}% % \end{macrocode} % Loop through each character of |#2|. % \begin{macrocode} \whiledo{\value{@@letterindex} < \value{@@stringsize}}{% \addtocounter{@@letterindex}{1}% % \end{macrocode} % Test if the |@@letterindex| character of string |#2| equals |#3|. % If so, add to tally. % \begin{macrocode} \testmatchingchar{#2}{\arabic{@@letterindex}}{#3}% \ifmatchingchar\addtocounter{@charsfound}{1}\fi }% \edef\theresult{\arabic{@charsfound}}% \if q#1\else\theresult\fi% \?} % \end{macrocode} % \end{macro} % \begin{macro}{\whereischar} % Similar to |\findchars|, but instead finds first occurance of match % character |#3| within |#2| and returns its location within |#2|. % \begin{macrocode} % CHECKS TO FIND LOCATION OF FIRST OCCURANCE OF [#3] IN STRING [#2]. % THE LOCATION IS PRINTED OUT, EXCEPT WHEN [#1]=q, QUIET % MODE. RESULT IS ALSO STORED IN \theresult . TO FIND SPACES, ARG3 % SHOULD BE SET TO {~}, NOT { }. \newcommand\whereischar[3][v]{\+% \@getstringlength{#2}{@@stringsize}% \edef\@theresult{0}% \setcounter{@@letterindex}{0}% % \end{macrocode} % Loop through characters of |#2| sequentially. % \begin{macrocode} \whiledo{\value{@@letterindex} < \value{@@stringsize}}{% \addtocounter{@@letterindex}{1}% % \end{macrocode} % Look for match. If found, save character-location index, % and reset loop index to break from loop. % \begin{macrocode} \testmatchingchar{#2}{\arabic{@@letterindex}}{#3}% \ifmatchingchar% \edef\@theresult{\the@@letterindex}% \setcounter{@@letterindex}{\the@@stringsize}% \fi }% \edef\theresult{\@theresult}% \if q#1\else\theresult\fi% \?} % \end{macrocode} % \end{macro} % \begin{macro}{\whereisword} % Finds location of specified word (|#3|) in string |#2|. % \begin{macrocode} % LIKE \whereischar, EXCEPT FOR WORDS \newcommand\whereisword[3][v]{\+% \setcounter{@skipped}{0}% % \end{macrocode} % |\@@@@teststring| initially contains |#2|. As false alarms are % located, the string will be redefined to lop off initial characters % of string. % \begin{macrocode} \edef\@@@@teststring{#2}% \edef\@matchstring{#3}% \@getstringlength{#2}{@@stringsize}% \setcounter{@@@stringsize}{\value{@@stringsize}}% \@getstringlength{#3}{@matchsize}% \setcounter{@matchmax}{\the@@stringsize}% \addtocounter{@matchmax}{-\the@matchsize}% \addtocounter{@matchmax}{1}% \setcounter{@flag}{0}% % \end{macrocode} % Define |\matchchar| as the first character of the match string (|#3|). % \begin{macrocode} \substring[e]{#3}{1}{1}% \edef\matchchar{\thestring}% \whiledo{\the@flag = 0}{% % \end{macrocode} % Look for first character of match string within |\@@@@teststring|. % \begin{macrocode} \whereischar[q]{\@@@@teststring}{\matchchar}% \setcounter{@matchloc}{\theresult}% \ifthenelse{\equal{0}{\value{@matchloc}}}% % \end{macrocode} % If none found, we are done. % \begin{macrocode} {% \setcounter{@flag}{1}% }% % \end{macrocode} % If |\matchchar| is found, must determine if it is the beginning % of the match string, or just an extraneous match (\ie false alarm). % Extract substring % of |\@@@@teststring|, of a size equal to the match string. % Compare this extracted string with the match string. % \begin{macrocode} {% \setcounter{@matchend}{\theresult}% \addtocounter{@matchend}{\value{@matchsize}}% \addtocounter{@matchend}{-1}% \substring[e]{\@@@@teststring}{\the@matchloc}{\the@matchend}% \ifthenelse{\equal{\thestring}{\@matchstring}}% % \end{macrocode} % Found a match! Save the match location % \begin{macrocode} {% \setcounter{@flag}{1}% \addtocounter{@matchloc}{\the@skipped}% \edef\theresult{\the@matchloc}% }% % \end{macrocode} % False alarm. Determine if lopping off the leading characters of % |\@@@@teststring| (to discard the false-alarm occurance) is feasible. % If lopping would take one past the end of the string, % then no match is possible. If lopping permissible, redefine the % string |\@@@@teststring|, keeping track of the total number of % lopped-off characters in the counter |@skipped|. % \begin{macrocode} {% \addtocounter{@skipped}{\the@matchloc}% \addtocounter{@matchloc}{1}% \ifthenelse{\value{@matchloc} > \value{@matchmax}}% {% \setcounter{@flag}{1}% \edef\theresult{0}% }% {% \substring[e]{\@@@@teststring}{\the@matchloc}{\@MAXSTRINGSIZE}% \edef\@@@@teststring{\thestring}% }% }% }% }% \if q#1\else\theresult\fi% \?} % \end{macrocode} % \end{macro} % \begin{macro}{\findwords} % Finds the number of occurances of a word within the provided string % \begin{macrocode} % LIKE \findchar, EXCEPT FOR WORDS \newcommand\findwords[3][v]{% \+\edef\@@teststring{#2}\?% \edef\@@@teststring{\@@teststring}% \setcounter{@charsfound}{0}% \whiledo{\the@charsfound > -1}{% % \end{macrocode} % Seek occurance of |#3| in the string to be tested % \begin{macrocode} \whereisword[q]{\@@teststring}{#3}% \setcounter{@matchloc}{\theresult}% \ifthenelse{\the@matchloc = 0}% {% % \end{macrocode} % None found. Break from loop. % \begin{macrocode} \edef\theresult{\the@charsfound}% \setcounter{@charsfound}{-1}% }% {% % \end{macrocode} % Found. Increment count. % \begin{macrocode} \addtocounter{@charsfound}{1}% \addtocounter{@matchloc}{\the@matchsize}% \ifthenelse{\the@matchloc > \the@@stringsize}% {% % \end{macrocode} % This "find" takes us to the end-of-string. Break from loop now. % \begin{macrocode} \edef\theresult{\the@charsfound}% \setcounter{@charsfound}{-1}% }% {% % \end{macrocode} % More string to search. Lop off what has been searched from string to % be tested, and re-loop for next search. % \begin{macrocode} \substring[e]{\@@@teststring}{\the@matchloc}{\@MAXSTRINGSIZE}% \edef\@@teststring{\thestring}% \edef\@@@teststring{\@@teststring}% }% }% }% \if q#1\else\theresult\fi% } % \end{macrocode} % \end{macro} % \begin{macro}{\wordcount} % Counts words (space-separated text) in a string. Simply removes one % word at a time, counting the words as it goes. With each removal, % checks for non-zero string size remaining. % \begin{macrocode} % WORD COUNT \newcommand\wordcount[2][v]{\+% \edef\@argv{#2} \@getstringlength{\@argv}{@stringsize} \setcounter{@iargc}{0} \whiledo{\value{@stringsize} > 0}{% \addtocounter{@iargc}{1}% \removeword[e]{\@argv}% \edef\@argv{\thestring}% \@getstringlength{\@argv}{@stringsize}% } \edef\theresult{\arabic{@iargc}}% \if v#1\theresult\fi% \?} % \end{macrocode} % \end{macro} % \begin{macro}{\getargs} % Parse a string of arguments in Unix-like manner. Define |\argv| as |#2|. % Grabs leading word from |\argv| and puts it in |\argi|. Increment % argument count; remove leading word from |\argv|. Repeat this process, % with each new argument being placed in |\argii|, |\argiii|, |\argiv|, % \etc~ Continue until size of |\argv| is exhausted. % \begin{macrocode} % OBTAINS ARGUMENTS (WORDS) IN #1 ALA UNIX getarg COMMAND % narg CONTAINS NUMBER OF ARGUMENTS. ARGUMENTS CONTAINED IN % argi, argii, argiii, argiv, ETC. % v mode disabled \newcommand\getargs[2][q]{\+% \if v#1\def\@mode{q}\else\def\@mode{#1}\fi% \edef\@argv{#2}% \@getstringlength{\@argv}{@stringsize}% \setcounter{@iargc}{0}% \whiledo{\value{@stringsize} > 0}{% \addtocounter{@iargc}{1}% \getaword[\@mode]{\@argv}{1}% \expandafter\edef\csname arg\roman{@iargc}\endcsname{\thestring}% \removeword[e]{\@argv}% \edef\@argv{\thestring}% \@getstringlength{\@argv}{@stringsize}% }% \edef\narg{\arabic{@iargc}}% \?} % \end{macrocode} % \end{macro} % \begin{macrocode} %%%%% COMMANDS TO TEST STRINGS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \end{macrocode} % The following group of commands test for various alphanumeric % string conditions. % \begin{macro}{\isnextbyte} % This routine performs a simple test to determine if the first byte of % string |#3| matches the byte given by |#2|. The only problem is that % the test can produce a false negative if the first byte of the test % string equals the match byte and the second byte of the test string % equals the |SignalChar| (defined below). % % To resolve this possibility, the test is performed twice with two % different values for |\SignalChar|, only one of which can produce % a false negative for a given test string. If the two results match, % then that result gives the correct answer to the question of whether % the first byte of |#3| equals |#2|. If, however, the two results fail % to match, then one can assume that one of the results is a false % negative, and so a ``true'' condition results. % \begin{macrocode} % \end{macrocode} % The following two ``signal characters,'' used for the two tests, % can be any two distinct characters. They are used solely % by |\isnextbyte|. % \begin{macrocode} \def\PrimarySignalChar{@} \def\SecondarySignalChar{`} % \isnextbyte NEEDS TO OPERATE IN RAW (SINGLE BYTE) MODE SO AS TO % PERFORM TESTS FOR PRESENCE OF \EscapeChar % \end{macrocode} % Incidentally, % |\isnextbyte| can and is used by \stringstrings to detect % multi-byte characters in a manner which may also be employed by the % user. To do this: % First, the string to be tested should be encoded. Then, |\isnextbyte| % may be used to check for |\EscapeChar| which is how every multi-byte % character will begin its encoding by the \stringstrings package. % If |\EscapeChar| is detected as the next character, then the string to % test may have its leading byte gobbled and the next character (called % the Escape Code) may be tested, and compared against the known % \stringstrings escape codes. The combination of % Escape-Character/Escape-Code is how all multi-byte characters are % encoded by the \stringstrings package. % \begin{macrocode} \newcommand\isnextbyte[3][v]{% % \end{macrocode} % Here's the first test\ldots % \begin{macrocode} \let\SignalChar\PrimarySignalChar% \edef\@x{\if #2#3\else\SignalChar\fi}% \edef\@x{\if \SignalChar\@x F\else T\fi}% % \end{macrocode} % \ldots and the second % \begin{macrocode} \let\SignalChar\SecondarySignalChar% \edef\@y{\if #2#3\else\SignalChar\fi}% \edef\@y{\if \SignalChar\@y F\else T\fi}% % \end{macrocode} % If the two tests produced the same result, then a comparison of |\@x\@y| % and |\@y\@x| will show it. % \begin{macrocode} % BECAUSE THE METHOD ONLY PRODUCES FALSE NEGATIVES, IF RESULTS DON'T % AGREE FROM USING TWO DIFFERENT SIGNAL CHARACTERS, RESULT MUST BE TRUE. \ifthenelse{\equal{\@x\@y}{\@y\@x}} {\edef\theresult{\@x}}% % CORRECT THE FALSE NEGATIVE {\edef\theresult{T}}% \if q#1\else\theresult\fi } % \end{macrocode} % \end{macro} % \begin{macro}{\testmatchingchar} % This routine checks for a specified match-character within a target % string. Unlike |\isnextbyte|, this % routine checks for characters (single- or multi-byte) and not just % individual bytes. Additionally, rather than testing the % match-character against the first byte of the test-string, the user % specifies (through |#2|) which byte of the test-string should be % compared to the match-character. % % This routine is not as efficient as |\isnextbyte|, but much more % versatile. % \begin{macrocode} % CHECKS TO SEE IF [#2]'th CHARACTER IN STRING [#1] EQUALS [#3] % RESULT STORED IN BOOLEAN \ifmatchingchar \newif\ifmatchingchar \newcommand\testmatchingchar[3]{% \setbox0=\hbox{% % \end{macrocode} % Extract desired character from test string % \begin{macrocode} \substring[e]{#1}{#2}{#2}\+% % \end{macrocode} % Determine if the match-character is a multi-byte symbol. % \begin{macrocode} \isnextbyte[q]{\EscapeChar}{#3}% \if T\theresult% % \end{macrocode} % Is the tested character also a multi-byte symbol? % \begin{macrocode} \isnextbyte[q]{\EscapeChar}{\thestring}% \if T\theresult% % \end{macrocode} % Yes it is\ldots Therefore, compare codes following the escape character % \begin{macrocode} \edef\@testcode{\expandafter\@DiscardNextChar\expandafter{#3}}% \edef\@teststring{\@DiscardNextChar{\thestring}}% \if \@teststring\@testcode\matchingchartrue\else\matchingcharfalse\fi \else % \end{macrocode} % No, we are comparing a normal character against a multi-byte symbol % (apples and oranges), a false comparison. % \begin{macrocode} \global\matchingcharfalse% \fi \else % \end{macrocode} % No, we are comparing two normal one-byte characters, not a mult-byte % character. % \begin{macrocode} \if \thestring#3\global\matchingchartrue\else\global\matchingcharfalse\fi \fi}% \?} % \end{macrocode} % \end{macro} % \begin{macro}{\testcapitalized} % This routine checks to see if first character of string is % capitalized. The only quirk is that the routine must ascertain % whether that character is a single-byte character or a multi-byte % character. % \begin{macrocode} \newif\ifcapitalized \newcommand\testcapitalized[1]{\+% \setbox0=\hbox{% \isnextbyte[q]{\EscapeChar}{#1}% \if T\theresult% \def\EncodingTreatment{e}% \edef\rotatingword{#1}% % \end{macrocode} % Rotate the first [multi-byte] character of the string to the end % of the string, lowering its case. Store as |\@stringA|. % \begin{macrocode} \def\AlphaCapsTreatment{2}% \@defineactions% \edef\@stringA{\ESCrotate{\expandafter\@gobble\rotatingword}}% % \end{macrocode} % Rotate the first [multi-byte] character of the string to the end % of the string, retaining its case. Store as |\@stringB|. % \begin{macrocode} \def\AlphaCapsTreatment{1}% \@defineactions% \edef\@stringB{\ESCrotate{\expandafter\@gobble\rotatingword}}% \else % \end{macrocode} % \ldots or, if the first character is a normal one-byte character\ldots % Rotate the first [normal] character of the string to the end % of the string, lowering its case. Store as |\@stringA|. % \begin{macrocode} \def\AlphaCapsTreatment{2}% \edef\@stringA{\@rotate{#1}}% % \end{macrocode} % Rotate the first [normal] character of the string to the end % of the string, retaining its case. Store as |\@stringB|. % \begin{macrocode} \def\AlphaCapsTreatment{1}% \edef\@stringB{\@rotate{#1}}% \fi % \end{macrocode} % Compare strings A and B, to see if changing the case of first letter % altered the string % \begin{macrocode} \ifthenelse{\equal{\@stringA}{\@stringB}}% {\global\capitalizedfalse}{\global\capitalizedtrue}}\?% \defaultTreatments% } % \end{macrocode} % \end{macro} % \begin{macro}{\testuncapitalized} % This routine is the complement of |\testcapitalized|. The only % difference is that the |\@stringA| has its case made upper for the % comparison, instead of lowered. % \begin{macrocode} \newif\ifuncapitalized \newcommand\testuncapitalized[1]{\+% \setbox0=\hbox{% \isnextbyte[q]{\EscapeChar}{#1}% \if T\theresult% \def\EncodingTreatment{e}% \edef\rotatingword{#1}% \def\AlphaTreatment{2}% \@defineactions% \edef\@stringA{\ESCrotate{\expandafter\@gobble\rotatingword}}% \def\AlphaTreatment{1}% \@defineactions% \edef\@stringB{\ESCrotate{\expandafter\@gobble\rotatingword}}% \else \def\AlphaTreatment{2}% \edef\@stringA{\@rotate{#1}}% \def\AlphaTreatment{1}% \edef\@stringB{\@rotate{#1}}% \fi \ifthenelse{\equal{\@stringA}{\@stringB}}% {\global\uncapitalizedfalse}{\global\uncapitalizedtrue}}\?% \defaultTreatments% } % \end{macrocode} % \end{macro} % \begin{macro}{\testleadingalpha} % Test if the leading character of the string is alphabetic. This is % simply accomplished by checking whether the string is either % capitalized or uncapitalized. If non-alphabetic, it will show % up as false for both those tests. % \begin{macrocode} \newif\ifleadingalpha \newcommand\testleadingalpha[1]{% \testcapitalized{#1}% \ifcapitalized \leadingalphatrue% \else \testuncapitalized{#1}% \ifuncapitalized \leadingalphatrue% \else \leadingalphafalse% \fi \fi } % \end{macrocode} % \end{macro} % \begin{macro}{\testuppercase} % Checks to see if all alphabetic characters in a string are uppercase. % Non-alphabetic characters don't affect the result, unless the string % is composed solely of nonalphabetic characters, in which case the test % results is false. % \begin{macrocode} \newif\ifuppercase \newcommand\testuppercase[1]{% \setbox0=\hbox{% % \end{macrocode} % Strip all non-alphabetic characters. Save as |\@stringA|. % \begin{macrocode} \Treatments{1}{1}{0}{0}{0}{0}% \substring[e]{#1}{1}{\@MAXSTRINGSIZE}% \edef\@stringA{\thestring}% % \end{macrocode} % Lower the case of all uppercase characters in |\@stringA|. Save as % |\@stringB|. Compare these two strings. % \begin{macrocode} \def\AlphaTreatment{2}% \substring[e]{#1}{1}{\@MAXSTRINGSIZE}% \edef\@stringB{\thestring}% \ifthenelse{\equal{\@stringA}{\@stringB}}% {% % \end{macrocode} % If the strings are equal, then all the alphabetic characters in the % original string were uppercase. Need only check to make sure at % least one alphabetic character was present in the original string. % \begin{macrocode} \@getstringlength{\@stringA}{@stringsize}% \ifthenelse{\value{@stringsize} = 0}% {\global\uppercasefalse}{\global\uppercasetrue}% }% % \end{macrocode} % If strings are not equal, then the alphabetic characters of the % original string were not all uppercase. Test false. % \begin{macrocode} {\global\uppercasefalse}}% \defaultTreatments% } % \end{macrocode} % \end{macro} % \begin{macro}{\ifsolelyuppercase} % Compare the original string to one made solely uppercase. If they are % equal (and not composed solely of blankspaces), then the original % string was solely uppercase to begin with. % \begin{macrocode} \newif\ifsolelyuppercase \newcommand\testsolelyuppercase[1]{% \setbox0=\hbox{% \stringencode{#1}% \edef\@stringA{\thestring}% \solelyuppercase[e]{#1}% \edef\@stringB{\thestring}% \ifthenelse{\equal{\@stringA}{\@stringB}}% {% \noblanks[q]{\@stringA}% \@getstringlength{\thestring}{@stringsize}% \ifthenelse{\value{@stringsize} = 0}% {\global\solelyuppercasefalse}{\global\solelyuppercasetrue}% }% {\global\solelyuppercasefalse}}% \defaultTreatments% } % \end{macrocode} % \end{macro} % \begin{macro}{\testlowercase} % This routine is the complement to |\testuppercase|, with corresponding % logic. % \begin{macrocode} \newif\iflowercase \newcommand\testlowercase[1]{% \setbox0=\hbox{% \Treatments{1}{1}{0}{0}{0}{0}% \substring[e]{#1}{1}{\@MAXSTRINGSIZE}% \edef\@stringA{\thestring}% \def\AlphaCapsTreatment{2}% \substring[e]{#1}{1}{\@MAXSTRINGSIZE}% \edef\@stringB{\thestring}% \ifthenelse{\equal{\@stringA}{\@stringB}}% {% \@getstringlength{\@stringA}{@stringsize}% \ifnum\value{@stringsize}= 0\relax% \global\lowercasefalse\else\global\lowercasetrue\fi% }% {\global\lowercasefalse}}% \defaultTreatments% } % \end{macrocode} % \end{macro} % \begin{macro}{\testsolelylowercase} % This routine is the complement to |\testsolelyuppercase|, with % corresponding logic. % \begin{macrocode} \newif\ifsolelylowercase \newcommand\testsolelylowercase[1]{% \setbox0=\hbox{% \stringencode{#1}% \edef\@stringA{\thestring}% \solelylowercase[e]{#1}% \edef\@stringB{\thestring}% \ifthenelse{\equal{\@stringA}{\@stringB}}% {% \noblanks[q]{\@stringA}% \@getstringlength{\thestring}{@stringsize}% \ifthenelse{\value{@stringsize} = 0}% {\global\solelylowercasefalse}{\global\solelylowercasetrue}% }% {\global\solelylowercasefalse}}% \defaultTreatments% } % \end{macrocode} % \end{macro} % \begin{macro}{\testalphabetic} % Comparable to |\testsolelyuppercase| and % |\testsolelylowercase| in its logic, this routine tests whether % the string is purely alphabetic or not. % \begin{macrocode} \newif\ifalphabetic \newcommand\testalphabetic[1]{% \setbox0=\hbox{% \stringencode{#1}% \edef\@stringA{\thestring}% \alphabetic[e]{#1}% \edef\@stringB{\thestring}% \ifthenelse{\equal{\@stringA}{\@stringB}}% {% \noblanks[q]{\@stringA}% \@getstringlength{\thestring}{@stringsize}% \ifthenelse{\value{@stringsize} = 0}% {\global\alphabeticfalse}{\global\alphabetictrue}% }% {\global\alphabeticfalse}}% \defaultTreatments% } % \end{macrocode} % \end{macro} % \begin{macrocode} % %%%%% SUPPORT ROUTINES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % \end{macrocode} % The following routines support the execution of the \stringstrings % package. % \begin{macro}{\ESCrotate} % After the escape character has been ascertained as the next character, % this routine operates on the subsequent escape code to rotate the % symbol to end of string, in the fashion of macro |\@rotate|. % \begin{macrocode} \newcommand\ESCrotate[1]{% \if\UvariCode#1\@uvariaction\else \if\UvariiCode#1\@uvariiaction\else \if\UvariiiCode#1\@uvariiiaction\else \if\@fromcode#1\@tostring\else \if\PipeCode#1\@pipeaction\else \if\DollarCode#1\@dollaraction\else \if\CaratCode#1\@carataction\else \if\CircumflexCode#1\@circumflexaction\else \if\TildeCode#1\@tildeaction\else \if\UmlautCode#1\@umlautaction\else \if\GraveCode#1\@graveaction\else \if\AcuteCode#1\@acuteaction\else \if\MacronCode#1\@macronaction\else \if\OverdotCode#1\@overdotaction\else \if\LeftBraceCode#1\@leftbraceaction\else \if\RightBraceCode#1\@rightbraceaction\else \if\UnderscoreCode#1\@underscoreaction\else \if\DaggerCode#1\@daggeraction\else \if\DoubleDaggerCode#1\@doubledaggeraction\else \if\SectionSymbolCode#1\@sectionsymbolaction\else \if\PilcrowCode#1\@pilcrowaction\else \if\LBCode#1\@lbaction\else \if\RBCode#1\@rbaction\else \if\BreveCode#1\@breveaction\else \if\CaronCode#1\@caronaction\else \if\DoubleAcuteCode#1\@doubleacuteaction\else \if\CedillaCode#1\@cedillaaction\else \if\UnderdotCode#1\@underdotaction\else \if\ArchJoinCode#1\@archjoinaction\else \if\LineUnderCode#1\@lineunderaction\else \if\CopyrightCode#1\@copyrightaction\else \if\PoundsCode#1\@poundsaction\else \if\AEscCode#1\@AEscaction\else \if\aescCode#1\@aescaction\else \if\OEthelCode#1\@OEthelaction\else \if\oethelCode#1\@oethelaction\else \if\AngstromCode#1\@Angstromaction\else \if\angstromCode#1\@angstromaction\else \if\SlashedOCode#1\@slashedOaction\else \if\SlashedoCode#1\@slashedoaction\else \if\BarredlCode#1\@barredlaction\else \if\BarredLCode#1\@barredLaction\else \if\EszettCode#1\@eszettaction\else \expandafter\@gobble#1\undecipherable% \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi } % \end{macrocode} % \end{macro} % \begin{macro}{\@getnextword} % A low-level routine designed to extract the next [space-delimited] % word of the primary % argument. It has several quirks: if the passed string has one leading % space, it is included as part of next word. If it has two leading % [hard]spaces, the 2$^\mathrm{nd}$ hard space \textit{is} the next word. % Using the higher-level |\getnextword| deals automatically with % these abberant possibilities. % \begin{macrocode} \newcommand\@getnextword[2][v]{% \defaultTreatments% \def\SeekBlankSpace{2}% \substring[#1]{#2}{1}{\@MAXSTRINGSIZE}% \def\SeekBlankSpace{0}% } % \end{macrocode} % \end{macro} % \begin{macro}{\@retokenizechar} % This command is the guts of the retokenize command. It grabs the % character provided in string |#1| and assigns it to a unique token % whose name is created from the string |#2|. The command has two % primary |\if| branches. The first branch is taken if the % character is a special two-byte-encoded escape-sequence, while % the second branch is taken if the character is a |&|, |%|, |#|, % a blankspace, or any simple one-byte character. % \begin{macrocode} \newcommand\@retokenizechar[2]{% \isnextbyte[q]{\EscapeChar}{#1}% \if T\theresult% \edef\@ESCcode{\expandafter\@gobble#1}% \if\UvariCode\@ESCcode% \expandafter\def\csname#2\endcsname{\Uvari}\else \if\UvariiCode\@ESCcode% \expandafter\def\csname#2\endcsname{\Uvarii}\else \if\UvariiiCode\@ESCcode% \expandafter\def\csname#2\endcsname{\Uvariii}\else \if\PipeCode\@ESCcode% \expandafter\def\csname#2\endcsname{\Pipe}\else \if\DollarCode\@ESCcode% \expandafter\def\csname#2\endcsname{\$}\else \if\CaratCode\@ESCcode% \expandafter\def\csname#2\endcsname{\Carat}\else \if\CircumflexCode\@ESCcode% \expandafter\def\csname#2\endcsname{\^}\else \if\TildeCode\@ESCcode% \expandafter\def\csname#2\endcsname{\~}\else \if\UmlautCode\@ESCcode% \expandafter\def\csname#2\endcsname{\"}\else \if\GraveCode\@ESCcode% \expandafter\def\csname#2\endcsname{\`}\else \if\AcuteCode\@ESCcode% \expandafter\def\csname#2\endcsname{\'}\else \if\MacronCode\@ESCcode% \expandafter\def\csname#2\endcsname{\=}\else \if\OverdotCode\@ESCcode% \expandafter\def\csname#2\endcsname{\.}\else \if\LeftBraceCode\@ESCcode% \expandafter\def\csname#2\endcsname{\{}\else \if\RightBraceCode\@ESCcode% \expandafter\def\csname#2\endcsname{\}}\else \if\UnderscoreCode\@ESCcode% \expandafter\def\csname#2\endcsname{\_}\else \if\DaggerCode\@ESCcode% \expandafter\def\csname#2\endcsname{\dag}\else \if\DoubleDaggerCode\@ESCcode% \expandafter\def\csname#2\endcsname{\ddag}\else \if\SectionSymbolCode\@ESCcode% \expandafter\def\csname#2\endcsname{\S}\else \if\PilcrowCode\@ESCcode% \expandafter\def\csname#2\endcsname{\P}\else \if\LBCode\@ESCcode% \expandafter\def\csname#2\endcsname{\SaveLB}\else \if\RBCode\@ESCcode% \expandafter\def\csname#2\endcsname{\SaveRB}\else \if\BreveCode\@ESCcode\expandafter\def\csname#2\endcsname{\u}\else \if\CaronCode\@ESCcode\expandafter\def\csname#2\endcsname{\v}\else \if\DoubleAcuteCode\@ESCcode\expandafter\def\csname#2\endcsname{\H}\else \if\CedillaCode\@ESCcode\expandafter\def\csname#2\endcsname{\c}\else \if\UnderdotCode\@ESCcode\expandafter\def\csname#2\endcsname{\d}\else \if\ArchJoinCode\@ESCcode\expandafter\def\csname#2\endcsname{\t}\else \if\LineUnderCode\@ESCcode\expandafter\def\csname#2\endcsname{\b}\else \if\CopyrightCode\@ESCcode\expandafter\def\csname#2\endcsname{\copyright}\else \if\PoundsCode\@ESCcode\expandafter\def\csname#2\endcsname{\pounds}\else \if\AEscCode\@ESCcode\expandafter\def\csname#2\endcsname{\AE}\else \if\aescCode\@ESCcode\expandafter\def\csname#2\endcsname{\ae}\else \if\OEthelCode\@ESCcode\expandafter\def\csname#2\endcsname{\OE}\else \if\oethelCode\@ESCcode\expandafter\def\csname#2\endcsname{\oe}\else \if\AngstromCode\@ESCcode\expandafter\def\csname#2\endcsname{\AA}\else \if\angstromCode\@ESCcode\expandafter\def\csname#2\endcsname{\aa}\else \if\SlashedOCode\@ESCcode\expandafter\def\csname#2\endcsname{\O}\else \if\SlashedoCode\@ESCcode\expandafter\def\csname#2\endcsname{\o}\else \if\BarredlCode\@ESCcode\expandafter\def\csname#2\endcsname{\l}\else \if\BarredLCode\@ESCcode\expandafter\def\csname#2\endcsname{\L}\else \if\EszettCode\@ESCcode\expandafter\def\csname#2\endcsname{\ss}\else \expandafter\def\csname#2\endcsname{\undecipherable}% \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \else \expandafter\ifx\expandafter\% \expandafter\def\csname#2\endcsname{\&}\else \expandafter\ifx\expandafter\%#1% \expandafter\def\csname#2\endcsname{\%}\else \expandafter\ifx\expandafter\##1% \expandafter\def\csname#2\endcsname{\#}\else \if\EncodedBlankSpace#1\expandafter\def\csname#2\endcsname{\ }\else \expandafter\edef\csname#2\endcsname{#1}% \fi \fi \fi \fi \fi } % \end{macrocode} % \end{macro} % \begin{macro}{\@defineactions} % This routine defines how encoded characters are to be treated by the % |\ESCrotate| routine, depending on the [encoding, capitalization, % blank, symbol, \textit{etc.}] treatments that have % been \textit{a priori} specified. % \begin{macrocode} % \@blankaction AND OTHER ...action'S ARE SET, DEPENDING ON VALUES OF % TREATMENT FLAGS. CHARS ARE EITHER ENCODED, DECODED, OR REMOVED. \newcommand\@defineactions{% % SET UP TREATMENT FOR SPACES, ENCODED SPACES, AND [REENCODED] SYMBOLS \if e\EncodingTreatment% % ENCODE SPACES, KEEP ENCODED SPACES ENCODED, ENCODE SYMBOLS. \edef\@blankaction{\EncodedBlankSpace}% \def\@dollaraction{\EncodedDollar}% \def\@pipeaction{\EncodedPipe}% \def\@uvariaction{\EncodedUvari}% \def\@uvariiaction{\EncodedUvarii}% \def\@uvariiiaction{\EncodedUvariii}% \def\@carataction{\EncodedCarat}% \def\@circumflexaction{\EncodedCircumflex}% \def\@tildeaction{\EncodedTilde}% \def\@umlautaction{\EncodedUmlaut}% \def\@graveaction{\EncodedGrave}% \def\@acuteaction{\EncodedAcute}% \def\@macronaction{\EncodedMacron}% \def\@overdotaction{\EncodedOverdot}% \def\@breveaction{\EncodedBreve}% \def\@caronaction{\EncodedCaron}% \def\@doubleacuteaction{\EncodedDoubleAcute}% \def\@cedillaaction{\EncodedCedilla}% \def\@underdotaction{\EncodedUnderdot}% \def\@archjoinaction{\EncodedArchJoin}% \def\@lineunderaction{\EncodedLineUnder}% \def\@copyrightaction{\EncodedCopyright}% \def\@poundsaction{\EncodedPounds}% \def\@leftbraceaction{\EncodedLeftBrace}% \def\@rightbraceaction{\EncodedRightBrace}% \def\@underscoreaction{\EncodedUnderscore}% \def\@daggeraction{\EncodedDagger}% \def\@doubledaggeraction{\EncodedDoubleDagger}% \def\@sectionsymbolaction{\EncodedSectionSymbol}% \def\@pilcrowaction{\EncodedPilcrow}% \def\@eszettaction{\EncodedEszett}% \def\@lbaction{\EncodedLB}% \def\@rbaction{\EncodedRB}% \if 2\AlphaCapsTreatment% \def\@AEscaction{\Encodedaesc}% \def\@OEthelaction{\Encodedoethel}% \def\@Angstromaction{\Encodedangstrom}% \def\@slashedOaction{\EncodedSlashedo}% \def\@barredLaction{\EncodedBarredl}% \else \def\@AEscaction{\EncodedAEsc}% \def\@OEthelaction{\EncodedOEthel}% \def\@Angstromaction{\EncodedAngstrom}% \def\@slashedOaction{\EncodedSlashedO}% \def\@barredLaction{\EncodedBarredL}% \fi \if 2\AlphaTreatment% \def\@aescaction{\EncodedAEsc}% \def\@oethelaction{\EncodedOEthel}% \def\@angstromaction{\EncodedAngstrom}% \def\@slashedoaction{\EncodedSlashedO}% \def\@barredlaction{\EncodedBarredL}% \else \def\@aescaction{\Encodedaesc}% \def\@oethelaction{\Encodedoethel}% \def\@angstromaction{\Encodedangstrom}% \def\@slashedoaction{\EncodedSlashedo}% \def\@barredlaction{\EncodedBarredl}% \fi \else % EncodingTreatment=v or q: % LEAVE SPACES ALONE; RESTORE ENCODED SPACES AND SYMBOLS \def\@blankaction{\BlankSpace}% \def\@dollaraction{\Dollar}% \def\@pipeaction{\Pipe}% \def\@uvariaction{\Uvari}% \def\@uvariiaction{\Uvarii}% \def\@uvariiiaction{\Uvariii}% \def\@carataction{\Carat}% \def\@circumflexaction{\Circumflex}% \def\@tildeaction{\Tilde}% \def\@umlautaction{\Umlaut}% \def\@graveaction{\Grave}% \def\@acuteaction{\Acute}% \def\@macronaction{\Macron}% \def\@overdotaction{\Overdot}% \def\@breveaction{\Breve}% \def\@caronaction{\Caron}% \def\@doubleacuteaction{\DoubleAcute}% \def\@cedillaaction{\Cedilla}% \def\@underdotaction{\Underdot}% \def\@archjoinaction{\ArchJoin}% \def\@lineunderaction{\LineUnder}% \def\@copyrightaction{\Copyright}% \def\@poundsaction{\Pounds}% \def\@leftbraceaction{\LeftBrace}% \def\@rightbraceaction{\RightBrace}% \def\@underscoreaction{\Underscore}% \def\@daggeraction{\Dagger}% \def\@doubledaggeraction{\DoubleDagger}% \def\@sectionsymbolaction{\SectionSymbol}% \def\@pilcrowaction{\Pilcrow}% \def\@eszettaction{\Eszett}% \def\@lbaction{\UnencodedLB}% \def\@rbaction{\UnencodedRB}% \if 2\AlphaCapsTreatment% \def\@AEscaction{\aesc}% \def\@OEthelaction{\oethel}% \def\@Angstromaction{\angstrom}% \def\@slashedOaction{\Slashedo}% \def\@barredLaction{\Barredl}% \else \def\@AEscaction{\AEsc}% \def\@OEthelaction{\OEthel}% \def\@Angstromaction{\Angstrom}% \def\@slashedOaction{\SlashedO}% \def\@barredLaction{\BarredL}% \fi \if 2\AlphaTreatment% \def\@aescaction{\AEsc}% \def\@oethelaction{\OEthel}% \def\@angstromaction{\Angstrom}% \def\@slashedoaction{\SlashedO}% \def\@barredlaction{\BarredL}% \else \def\@aescaction{\aesc}% \def\@oethelaction{\oethel}% \def\@angstromaction{\angstrom}% \def\@slashedoaction{\Slashedo}% \def\@barredlaction{\Barredl}% \fi \fi % REMOVE SPACES AND ENCODED SPACES? \if 0\BlankTreatment% \edef\@blankaction{}% \fi % REMOVE ENCODED SYMBOLS? \if 0\SymbolTreatment% \def\@dollaraction{}% \def\@pipeaction{}% \def\@carataction{}% \def\@circumflexaction{}% \def\@tildeaction{}% \def\@umlautaction{}% \def\@graveaction{}% \def\@acuteaction{}% \def\@macronaction{}% \def\@overdotaction{}% \def\@breveaction{}% \def\@caronaction{}% \def\@doubleacuteaction{}% \def\@cedillaaction{}% \def\@underdotaction{}% \def\@archjoinaction{}% \def\@lineunderaction{}% \def\@copyrightaction{}% \def\@poundsaction{}% \def\@leftbraceaction{}% \def\@rightbraceaction{}% \def\@underscoreaction{}% \def\@daggeraction{}% \def\@doubledaggeraction{}% \def\@sectionsymbolaction{}% \def\@pilcrowaction{}% \def\@lbaction{}% \def\@rbaction{}% \fi % REMOVE ENCODED ALPHACAPS? \if 0\AlphaCapsTreatment% \def\@AEscaction{}% \def\@OEthelaction{}% \def\@Angstromaction{}% \def\@slashedOaction{}% \def\@barredLaction{}% \fi % REMOVE ENCODED ALPHA? \if 0\AlphaTreatment% \def\@aescaction{}% \def\@oethelaction{}% \def\@angstromaction{}% \def\@slashedoaction{}% \def\@barredlaction{}% \def\@eszettaction{}% \fi } % \end{macrocode} % \end{macro} % \begin{macro}{\@forcecapson} % Force capitalization of strings processed by |\substring| for the % time being. % \begin{macrocode} \newcommand\@forcecapson{% \def\AlphaTreatment{2}% \def\AlphaCapsTreatment{1}% } % \end{macrocode} % \end{macro} % \begin{macro}{\@relaxcapson} % Restore prior treatments following a period of enforced capitalization. % \begin{macrocode} \newcommand\@relaxcapson{% \let\AlphaTreatment\SaveAlphaTreatment% \let\AlphaCapsTreatment\SaveAlphaCapsTreatment% \@defineactions% } % \end{macrocode} % \end{macro} % \begin{macro}{\@decodepointer} % As pertains to arguments 3 and 4 of |\substring|, this routine % implements use of the |$| character to mean END-OF-STRING, % and |$-{|\textit{integer}|}| for addressing relative to the % END-OF-STRING. % \begin{macrocode} \newcommand\@decodepointer[2][\value{@stringsize}]{% \isnextbyte[q]{$}{#2}% \if T\theresult% \isnextbyte[q]{-}{\expandafter\@gobble#2}% \if T\theresult% \setcounter{@@@letterindex}{#1}% \@gobblearg{#2}{2}% \addtocounter{@@@letterindex}{-\gobbledword}% \edef\@fromtoindex{\value{@@@letterindex}}% \else \edef\@fromtoindex{#1}% \fi \else \edef\@fromtoindex{#2}% \fi } % \end{macrocode} % \end{macro} % \begin{macro}{\@getstringlength} % Get's string length of |#1|, puts result in counter |#2|. % \begin{macrocode} \newcommand\@getstringlength[2]{% \edef\@@teststring{#1\endofstring}% \ifthenelse{\equal{\@@teststring}{\endofstring}}% {\setcounter{#2}{0}}% {% \setcounter{@gobblesize}{1}% \whiledo{\value{@gobblesize} < \@MAXSTRINGSIZE}{% % \@gobblearg{\@@teststring}{1}% \edef\@@teststring{\gobbledword}% \ifthenelse{\equal{\@@teststring}{\endofstring}}% {\setcounter{#2}{\value{@gobblesize}}% \setcounter{@gobblesize}{\@MAXSTRINGSIZE}}% {\addtocounter{@gobblesize}{1}}% }% }% } % \end{macrocode} % \end{macro} % \begin{macro}{\@gobblearg} % Gobble first |#2| characters from string |#1|. The % result is stored in |\gobbledword|. Two-byte escape sequences, % when encountered, count as a single gobble. % \begin{macrocode} \newcommand\@gobblearg[2]{% \setcounter{@letterindex}{0}% \setcounter{@gobbleindex}{#2}% \edef\gobbledword{#1}% \whiledo{\value{@letterindex} < \value{@gobbleindex}}{% \isnextbyte[q]{\EscapeChar}{\gobbledword}% \if T\theresult% % GOBBLE ESCAPE CHARACTER \edef\gobbledword{\@DiscardNextChar{\gobbledword}}% \fi % GOBBLE NORMAL CHARACTER OR ESCAPE CODE \edef\gobbledword{\@DiscardNextChar{\gobbledword}}% \addtocounter{@letterindex}{1}% }% } % \end{macrocode} % \end{macro} % \begin{macro}{\@DiscardNextChar} % Remove the next character from the argument string. Since % |\@gobble| skips spaces, the routine must first look for the case of % a leading blankspace. If none is found, proceed with a normal % |\@gobble|. Note: as per \LaTeX{} convention, |\@DiscardNextChar| % treats double/multi-softspaces as single space. % \begin{macrocode} \newcommand\@DiscardNextChar[1]{% \expandafter\if\expandafter\BlankSpace#1\else \expandafter\@gobble#1% \fi } % \end{macrocode} % \end{macro} % \begin{macro}{\@convertsymboltostring} % Routine for converting an encodable symbol (|#3|) into string (|#4|), % for every occurance in the given string |#2|. % \begin{macrocode} \newcommand\@convertsymboltostring[4][v]{% \def\@fromcode{#3}% \def\@tostring{#4}% \def\EncodingTreatment{e}% \substring[e]{#2}{1}{\@MAXSTRINGSIZE}% \@convertoff% \if e#1\else\substring[#1]{\thestring}{1}{\@MAXSTRINGSIZE}\fi% } % \end{macrocode} % \end{macro} % \begin{macro}{\@convertbytetostring} % Routine for converting an plain byte (|#3|) into string (|#4|), % for every occurance in the given string |#2|. % \begin{macrocode} \newcommand\@convertbytetostring[4][v]{% \def\@frombyte{#3}% \def\@tostring{#4}% \def\EncodingTreatment{e}% \substring[e]{#2}{1}{\@MAXSTRINGSIZE}% \@convertoff% \if e#1\else\substring[#1]{\thestring}{1}{\@MAXSTRINGSIZE}\fi% } % \end{macrocode} % \end{macro} % \begin{macro}{\@treatleadingspaces} % This routine will address the leading spaces of string |#2|. If % argument |#3| is an 'x' character, those leading spaces will be % deleted from the string. Otherwise, those leading spaces will be % rotated to the end of the string. % \begin{macrocode} \newcommand\@treatleadingspaces[3][v]{\+% \defaultTreatments% \edef\thestring{#2}% \@getstringlength{\thestring}{@stringsize}% \setcounter{@maxrotation}{\value{@stringsize}}% \setcounter{@letterindex}{0}% \whiledo{\value{@letterindex} < \value{@maxrotation}}{% \addtocounter{@letterindex}{1}% \isnextbyte[q]{\EncodedBlankSpace}{\thestring}% \if F\theresult\isnextbyte[q]{\BlankSpace}{\thestring}\fi% \if T\theresult% \isnextbyte[q]{#3}{x}% \if F\theresult% % NORMAL OR ENCODED BLANK... ROTATE IT \edef\thestring{\@rotate{\thestring}}% \else % NORMAL OR ENCODED BLANK... DELETE IT (IF 3rd ARG=X) \@gobblearg{\thestring}{1}% \edef\thestring{\gobbledword}% \fi \else \setcounter{@maxrotation}{\value{@letterindex}}% \fi }\?% \substring[#1]{\thestring}{1}{\@MAXSTRINGSIZE}% } % \end{macrocode} % \end{macro} % \begin{macro}{\@convertoff} % This routine is an initialization routine to % guarantee that there is no conversion of |\@frombyte| to |\@tostring|, % until further notice. It accomplishes this % by setting up such that subsequent |\if\@frombyte| and % |\if\@fromcode| clauses will automatically fail. % \begin{macrocode} \newcommand\@convertoff{\def\@frombyte{xy}\def\@tostring{}% \def\@fromcode{xy}} \@convertoff % \end{macrocode} % \end{macro} % \begin{macro}{\@rotate} % The following code is the engine of the string manipulation routine. % It is a tree of successive \LaTeX{} commands (each of which is % composed of an |\if...| cascade) which have the net % effect of rotating the first letter of the string into the last % position. Depending on modes set by |\@defineactions| and % |\defaultTreatments|, the leading character is either encoded, % decoded, or removed in the process. % Note: |\@rotate| loses track of double/multi-spaces, per \LaTeX{} % convention, unless encoded blanks (|~|) are used. % \begin{macrocode} \newcommand\@rotate[1]{% % CHECK BYTE CONVERSION TEST FIRST \if \@frombyte#1\@tostring\else % MUST CHECK FOR MULTI-BYTE CHARACTERS NEXT, SO THAT ENCODING CHARACTER % ISN'T MISTAKEN FOR A NORMAL CHARACTER LATER IN MACRO. \if 0\SymbolTreatment% \@removeExpandableSymbols{#1}% \else \@rotateExpandableSymbols{#1}% \fi \fi } \newcommand\@rotateExpandableSymbols[1]{% % INDIRECT (EXPANDABLE) SYMBOLS \expandafter\ifx\expandafter\\&\else \expandafter\ifx\expandafter\%#1\%\else \expandafter\ifx\expandafter\##1\#\else \@rotateBlankSpaces{#1}% \fi \fi \fi } \newcommand\@removeExpandableSymbols[1]{% % INDIRECT (EXPANDABLE) SYMBOLS \expandafter\ifx\expandafter\\else \expandafter\ifx\expandafter\%#1\else \expandafter\ifx\expandafter\##1\else \@rotateBlankSpaces{#1}% \fi \fi \fi } \newcommand\@rotateBlankSpaces[1]{% \expandafter\ifx\expandafter$#1$\else% <---RETAIN GOING INTO/FROM MATH MODE % THE FOLLOWING FINDS TILDES, BUT MUST COME AFTER EXPANDABLE SYMBOL % SEARCH, OR ELSE IT FINDS THEM TOO, BY MISTAKE. \if \EncodedBlankSpace#1\@blankaction\else% <--- FINDS REENCODED TILDE % THE FOLLOWING SHOULD FIND TILDES, BUT DOESN'T... THUS, COMMENTED OUT. % \expandafter\ifx\expandafter\EncodedBlankSpace#1\@blankaction\else \if \BlankSpace#1\@blankaction\else \if 2\AlphaTreatment% \@chcaseAlpha{#1}% \else \if 0\AlphaTreatment% \@removeAlpha{#1}% \else \@rotateAlpha{#1}% \fi \fi \fi % \fi \fi \fi } \newcommand\@rotateAlpha[1]{% % LOWERCASE \if a#1a\else \if b#1b\else \if c#1c\else \if d#1d\else \if e#1e\else \if f#1f\else \if g#1g\else \if h#1h\else \if i#1i\else \if j#1j\else \if k#1k\else \if l#1l\else \if m#1m\else \if n#1n\else \if o#1o\else \if p#1p\else \if q#1q\else \if r#1r\else \if s#1s\else \if t#1t\else \if u#1u\else \if v#1v\else \if w#1w\else \if x#1x\else \if y#1y\else \if z#1z\else \if 2\AlphaCapsTreatment% \@chcaseAlphaCaps{#1}% \else \if 0\AlphaCapsTreatment% \@removeAlphaCaps{#1}% \else \@rotateAlphaCaps{#1}% \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi } \newcommand\@removeAlpha[1]{% % LOWERCASE \if a#1\else \if b#1\else \if c#1\else \if d#1\else \if e#1\else \if f#1\else \if g#1\else \if h#1\else \if i#1\else \if j#1\else \if k#1\else \if l#1\else \if m#1\else \if n#1\else \if o#1\else \if p#1\else \if q#1\else \if r#1\else \if s#1\else \if t#1\else \if u#1\else \if v#1\else \if w#1\else \if x#1\else \if y#1\else \if z#1\else \if 2\AlphaCapsTreatment% \@chcaseAlphaCaps{#1}% \else \if 0\AlphaCapsTreatment% \@removeAlphaCaps{#1}% \else \@rotateAlphaCaps{#1}% \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi } \newcommand\@chcaseAlpha[1]{% % LOWERCASE TO UPPERCASE \if a#1A\else \if b#1B\else \if c#1C\else \if d#1D\else \if e#1E\else \if f#1F\else \if g#1G\else \if h#1H\else \if i#1I\else \if j#1J\else \if k#1K\else \if l#1L\else \if m#1M\else \if n#1N\else \if o#1O\else \if p#1P\else \if q#1Q\else \if r#1R\else \if s#1S\else \if t#1T\else \if u#1U\else \if v#1V\else \if w#1W\else \if x#1X\else \if y#1Y\else \if z#1Z\else \if 2\AlphaCapsTreatment% \@chcaseAlphaCaps{#1}% \else \if 0\AlphaCapsTreatment% \@removeAlphaCaps{#1}% \else \@rotateAlphaCaps{#1}% \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi } \newcommand\@rotateAlphaCaps[1]{% % UPPERCASE \if A#1A\else \if B#1B\else \if C#1C\else \if D#1D\else \if E#1E\else \if F#1F\else \if G#1G\else \if H#1H\else \if I#1I\else \if J#1J\else \if K#1K\else \if L#1L\else \if M#1M\else \if N#1N\else \if O#1O\else \if P#1P\else \if Q#1Q\else \if R#1R\else \if S#1S\else \if T#1T\else \if U#1U\else \if V#1V\else \if W#1W\else \if X#1X\else \if Y#1Y\else \if Z#1Z\else \if 0\NumeralTreatment% \@removeNumerals{#1}% \else \@rotateNumerals{#1}% \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi } \newcommand\@removeAlphaCaps[1]{% % UPPERCASE \if A#1\else \if B#1\else \if C#1\else \if D#1\else \if E#1\else \if F#1\else \if G#1\else \if H#1\else \if I#1\else \if J#1\else \if K#1\else \if L#1\else \if M#1\else \if N#1\else \if O#1\else \if P#1\else \if Q#1\else \if R#1\else \if S#1\else \if T#1\else \if U#1\else \if V#1\else \if W#1\else \if X#1\else \if Y#1\else \if Z#1\else \if 0\NumeralTreatment% \@removeNumerals{#1}% \else \@rotateNumerals{#1}% \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi } \newcommand\@chcaseAlphaCaps[1]{% % UPPERCASE TO LOWERCASE \if A#1a\else \if B#1b\else \if C#1c\else \if D#1d\else \if E#1e\else \if F#1f\else \if G#1g\else \if H#1h\else \if I#1i\else \if J#1j\else \if K#1k\else \if L#1l\else \if M#1m\else \if N#1n\else \if O#1o\else \if P#1p\else \if Q#1q\else \if R#1r\else \if S#1s\else \if T#1t\else \if U#1u\else \if V#1v\else \if W#1w\else \if X#1x\else \if Y#1y\else \if Z#1z\else \if 0\NumeralTreatment% \@removeNumerals{#1}% \else \@rotateNumerals{#1}% \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi } \newcommand\@rotateNumerals[1]{% % NUMERALS \if 1#11\else \if 2#12\else \if 3#13\else \if 4#14\else \if 5#15\else \if 6#16\else \if 7#17\else \if 8#18\else \if 9#19\else \if 0#10\else \if 0\PunctuationTreatment% \@removePunctuation{#1}% \else \@rotatePunctuation{#1}% \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi } \newcommand\@removeNumerals[1]{% % NUMERALS \if 1#1\else \if 2#1\else \if 3#1\else \if 4#1\else \if 5#1\else \if 6#1\else \if 7#1\else \if 8#1\else \if 9#1\else \if 0#1\else \if 0\PunctuationTreatment% \@removePunctuation{#1}% \else \@rotatePunctuation{#1}% \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi } \newcommand\@rotatePunctuation[1]{% % PUNCTUATION \if ;#1;\else \if :#1:\else \if '#1'\else \if "#1"\else \if ,#1,\else \if .#1.\else \if ?#1?\else \if `#1`\else \if !#1!\else \if 0\SymbolTreatment% \@removeDirectSymbols{#1}% \else \@rotateDirectSymbols{#1}% \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi } \newcommand\@removePunctuation[1]{% % PUNCTUATION \if ;#1\else \if :#1\else \if '#1\else \if "#1\else \if ,#1\else \if .#1\else \if ?#1\else \if `#1\else \if !#1\else \if 0\SymbolTreatment% \@removeDirectSymbols{#1}% \else \@rotateDirectSymbols{#1}% \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi } \newcommand\@rotateDirectSymbols[1]{% % DIRECT SYMBOLS \if /#1/\else \if @#1@\else \if *#1*\else \if (#1(\else \if )#1)\else \if -#1-\else \if _#1_\else \if =#1=\else \if +#1+\else \if [#1[\else \if ]#1]\else \if ^#1^\else% <--FOR SUPERSCRIPTS, NOT \^ \if <#1<\else \if >#1>\else \if |#1|\else \if &\else \@rotateUndecipherable{#1}% \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi } \newcommand\@removeDirectSymbols[1]{% % DIRECT SYMBOLS \if /#1\else \if @#1\else \if *#1\else \if (#1\else \if )#1\else \if -#1\else \if _#1\else \if =#1\else \if +#1\else \if [#1\else \if ]#1\else \if ^#1\else% <--FOR SUPERSCRIPTS, NOT \^ \if <#1\else \if >#1\else \if |#1\else \if \else \@rotateUndecipherable{#1}% \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi } \newcommand\@rotateUndecipherable[1]{% % REPLACE UNDECIPHERABLE SYMBOL WITH A TOKEN CHARACTER (DEFAULT .) \expandafter\@gobble#1\undecipherable% % DONE... CLOSE UP SHOP } % \end{macrocode} % \end{macro} % \begin{macrocode} \catcode`\&=4 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % \end{macrocode} % % \Finale \endinput % % End of file `stringstrings.dtx'.