# Detect which text “mode” (normal, italic, bold, etc.) is currently in use?

In my document, I'm often setting upper case words and abbreviations in small caps because it avoids breaking the flow (which upper case words does). Also, many words (like CUDA, for instance) are also entered as commands instead of directly as text.

Up to this point I have manually set these words in small caps where appropriate (like \textsc{\cuda}), but this becomes unnecessarily repetitive. What I would like to be able to do is to define a command like \cuda which prints CUDA in small caps where the text "mode" is normal roman, and sets CUDA in upper cases if the text mode is italics. The reason for doing this is the font I'm using doesn't support small caps in italics.

Hence I would like to be able to detect which text "mode" is currently in use, and act accordingly.

I've included a minimal example below to illustrate my point:

\documentclass{article}

\usepackage{textcase}

\newcommand{\cudaString}{CUDA}
\newcommand{\cuda}{\textsc{\MakeTextLowercase{\cudaString}}}

\begin{document}
Set \cuda in small caps here,
\itshape but do not set \cuda in small caps here.
\end{document}

-
There's little point in \newcommand{\cuda}{\textsc{CUDA}}, as it will appear in all caps anyway; it's probably \textsc{cuda}, isn't it? –  egreg Oct 15 '11 at 19:25
Ah of course; I forgot that in my code I use \MakeTextLowercase and I wrote the example code just from memory. –  gablin Oct 17 '11 at 8:51
So it would be better to show a real example, as solutions with \MakeUppercase might have problems. –  egreg Oct 17 '11 at 8:57
Probably. I've updated the example accordingly. –  gablin Oct 17 '11 at 9:07
–  Jubobs Mar 6 at 12:17

LaTeX's 'New Font Selection Scheme' (NFSS) stores information about the font in a number of macros. The macro \f@shape stores the shape: n for upright, it for italic and sc for small caps. \f@series stores the series: m for mid-weight and bx for bold, while \f@family stores the family: something like cmr for roman, cmss for sanserif and cmtt for monospaced (it's dependent on the current font).

Thus you can test for small caps using

\makeatletter
\newcommand*{\IfSmallCapsTF}{%
\ifx\f@shape\my@test@sc
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}
\newcommand*{\my@test@sc}{sc}
\makeatother

\IfSmallCapsTF{true-code}{false-code}

-
I would actually like to accept two answers - this on and egreg's - as I incorporated both to make a command which sets its argument in small caps if the current style is roman, fake small caps if it is italics, and otherwise just converts it to upper case. –  gablin Oct 17 '11 at 13:18
I'm wondering... Do you really have to define a command that expands to sc? Or is that name already stored in some kernel macro? –  Jubobs Mar 6 at 11:22
@Jubobs That I know of latex.ltx doesn't provide any useful shortcuts for these. Of course, with an up-to-date engine you can use \pdfstrcmp or similar for the test (\ifx likely faster if used many times). –  Joseph Wright Mar 6 at 12:01
@JosephWright Thanks. I need to perform a test on the current font shape, but I was wondering whether I was "reinventing the wheel" by defining those macros. –  Jubobs Mar 6 at 12:05

You may want to fake an italic small caps font:

\makeatletter
\DeclareRobustCommand{\SCorIT}[1]{%
\ifdim\fontdimen\@ne\font>\z@
\begingroup\check@mathfonts
\fontsize\sf@size\z@\selectfont
\MakeUppercase{#1}\endgroup
\else
\textsc{#1}%
\fi
}
\makeatother

\newcommand{\cuda}{\SCorIT{cuda}}


Depending on the font the result can turn out to be as desired. Beware that for bold face another test must be added.

If you use \MakeLowercase or textcase's \MakeTextLowercase for defining the acronym, you should modify the definition into

\makeatletter
\DeclareRobustCommand{\SCorIT}[1]{%
\ifdim\fontdimen\@ne\font>\z@
\begingroup\check@mathfonts
\fontsize\sf@size\z@\selectfont
\let\MakeTextLowercase\@firstofone % for textcase
\let\MakeLowercase\@firstofone     % for standard LaTeX
\MakeTextUppercase{#1}\endgroup
\else
\textsc{#1}%
\fi
}
\makeatother


that will avoid accumulating case changes.

The example was generated with the following code:

\documentclass{standalone}
\usepackage{textcase}
\makeatletter
\DeclareRobustCommand{\SCorIT}[1]{%
\ifdim\fontdimen\@ne\font>\z@
\begingroup\check@mathfonts
\fontsize\sf@size\z@\selectfont
\let\MakeTextLowercase\@firstofone
\MakeTextUppercase{#1}\endgroup
\else
\textsc{#1}%
\fi
}
\makeatother

\newcommand{\cudaString}{CUDA}
\newcommand{\cuda}{\SCorIT{\MakeTextLowercase{\cudaString}}}

\begin{document}

\hbox{Set \cuda{} in small caps here,\strut}
\hbox{\itshape but do not set \cuda{} in small caps here.\strut}

\end{document}

-
Could you please extend it to a minimal example? I keep getting compilation errors when I try to use it in my document. –  gablin Oct 17 '11 at 13:00
My apologies. I must have done something wrong the first time, because now I got it running. –  gablin Oct 17 '11 at 13:12

Stealing a bit from the definition of \em (seen using latexdef em), we can create a command \SCorUC that typesets its argument in small caps or uppercase depending on context:

\makeatletter
\newcommand{\SCorUC}[1]{\ifdim\fontdimen\@ne\font>\z@\MakeUppercase{#1}\else\textsc{#1}\fi}
\makeatother
\newcommand{\cuda}{\SCorUC{cuda}}

-