在使用自定义环境工作时\@startsection
,我发现在切换到newunicodechar
定义我的unicode字符后,分段标题给出了这个特殊的输出:
以下是代码:
\documentclass{article}
\usepackage[colorlinks]{hyperref}
\newcounter{lemma}
\makeatletter
\def\lemmamark{\@gobble}
\newenvironment{lemma}[1]{\@startsection{lemma}{3}{-1em}{\baselineskip}{.1\baselineskip}{\bfseries}{Lemma: #1}}{}
\makeatother
\usepackage{newunicodechar}
\def\textomega{ω} \newunicodechar{ω}{\ifmmode \omega \else \textomega \fi}
\usepackage{fontspec}
\setmainfont[Ligatures=TeX]{STIXGeneral}
\begin{document}
\begin{lemma}{Properties of ω text}
Some Test
\end{lemma}
\section{Properties of ω}
More Testing
\end{document}
以下更改不产生任何影响:
- 使用标准分段命令代替
\@startsection
(如示例输出所示) - 删除
\ifmmode
条件(我只是把它留在这里,这样你就能看到使用的原因\newunicodechar
) - 使用
\protect
内部\def\textomega
- 使用
\renewcommand
或\DeclareRobustCommand
定义\textomega
- 使用预定义的
\textomega
我知道我可能unicode-math
在这里用到它,但我仍然TeX Live 2011
发现它在一般情况下不够用。
我只会发布一个关于如何解决这个问题的自我回答,但我更感兴趣的是:为什么会发生这种情况?hyperref
这可能是或中的一个错误吗newunicodechar
?
这更奇怪了!对于其他类似的字符,不存在这样的问题。例如,ψ 代替 ω 可以与
\def\textpsi{ψ} \newunicodechar{ψ}{\ifmmode \psi \else \textpsi \fi}
答案1
软件包hyperref
生成书签并尝试从 LaTeX 的节系统中捕获书签标题。最困难的步骤是将以 TeX 字符串形式给出的标题转换为适合 PDF 书签标题的字符串。首先,重新定义许多宏以获得更合理的书签输出。还hyperref
利用 NFSS2 并使用编码PD1
和PU
PDFDocEncoding 或 Unicode(PDF 书签字符串中只允许使用这两种编码)。然后展开字符串(\edef
),并在之后的清理中检查标记。一个重要的步骤是\HyPsd@CheckCatcodes
控制标记。例如,$
用于切换到和从数学切换的被过滤掉。不幸的是,忘记了使用 e-TeX 定义的活动字符的情况
\protected
。这是字符的情况,ω
因为
\newunicodechar
。它在行中得到扩展\ifcat#1A% letter
。\HyPsd@CheckCatcodes
的扩展扩展ω
了\textomega
,在PU
编码中扩展为\83\311
的八进制表示U+03C9
。在这种情况下\8
,由两个带有 catcode 12(其他)的标记组成,\ifcat
成功并且剩余的标记泄漏:3\311
和A
来自预期标记比较的。
我将在 2012/07/30 v6.82w 中修复此问题hyperref
。添加了对受保护活动字符的额外测试,并将这些字符替换为具有相同字符代码的 catcode 12(其他)的字符。但是,必须忽略活动字符的宏文本,因为该宏文本可能会打印其他内容。使用 定义的宏\protected
未在 中展开\edef
。支持此类宏和字符的唯一方法是为 增加这些宏的适当重新定义\pdfstringdef
,例如:
\newunicodechar{ω}{ohm}
\pdfstringdefDisableCommands{%
\def ω{ohm}%
}
顺便说一句,请记住,\text<charname>
宏通常使用 NFSS2 系统 ( \DeclareTextSymbol
、\DeclareTextCommand
、 ...) 定义。这些命令定义如何根据当前编码排版宏。它们会默默覆盖宏的先前定义。
答案2
以下任何更改都将删除带有“3\311A”的虚假行:
- 删除
hyperref
包 - 删除以下语句
\newunicodechar{ω}
- 在……前面
\protect
放一个\textomega
\newunicodechar{ω}
使用
\protect
像这样的:\newcommand\unichar[3]{\newunicodechar{#1}{\protect{\ifmmode#2\else#3\fi}}} \def\textomega{ω} \unichar{ω}{\omega}{\textomega}
最后一种解决方案的优点是当使用大量此类语句时,代码简洁。
我发现了更多的事情。问题是,它fontspec
覆盖了我的定义\textomega
,因此当ω
由 定义的\newunicodechar
被扩展时,会使用fontspec
s\textomega
而不是我的。这解释了为什么另一方面使用来自\textomega
like 的不同命令\textpsi
会起作用:当您尝试使用它时会被告知,\textpsi
它在 EU1 编码中没有定义。
因此我可以在加载后简单地进行定义fontspec
,但是有一个更好的解决方案,可以完全解决这个问题:
\newunicodechar{ω}{\ifmmode\omega\else ω\fi}
正如我得出的结论egreg 的答案之一,在 的参数中使用unicode字符本身是完全可以的\newunicodechar
。所以现在不再\textomega
需要了。