\documentclass[]{article}
\usepackage{amsmath,graphicx,supertabular,hyperref,tabularx,ifthen}
\title{TIP \#425: Internationalization of Default Panic Callback on Windows}
\date{July 17, 2013}
\author{Jan Nijtmans}
\urlstyle{sf}
\setlength{\parskip}{1ex}
\setlength{\parindent}{0pt}
\def\tipversion$#1${\texttt{\$#1\$}}
\def\tiplangle#1{\ensuremath{<}}
\def\tiprangle#1{\ensuremath{>}}
\def\tipbar#1{\ensuremath{|}}
\def\tipmail#1#2{\(\langle\){\small\expandafter\url{#1@#2}}\(\rangle\)}
\ifx\pdfoutput\undefined
\newcommand{\tipimage}[2]{\typeout{Make sure you download #1.eps}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.eps}}{\includegraphics[width=0.8\textwidth]{#1.eps}}}
\newcommand{\tipxref}[1]{}
\newcommand{\tipxrefend}{}
\else
\newcommand{\tipimage}[2]{\typeout{Make sure you create #1.pdf}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.pdf}}{\includegraphics[width=0.8\textwidth]{#1.pdf}}}
\pdfcatalog{/PageMode /UseOutlines}
\newcommand{\tipxref}[1]{\pdfannotlink attr {/C [0.5 0.5 1.0] /Border [0 0 1]} goto name {#1}}
\newcommand{\tipxrefend}{\pdfendlink}
\fi
\newenvironment{tipabstract}{\begin{abstract}}{\end{abstract}}
\begin{document}\maketitle
\begin{center}\begin{tabularx}{\linewidth}{|r@{: }X|}\hline
\textbf{TIP \#425}&\textbf{Internationalization of Default Panic Callback on Windows}\\\hline
Author&

Jan Nijtmans \tipmail{jan.nijtmans}{gmail.com}
\\
Created&Wednesday, \(\text{17}^{\text{th}}\) July 2013\\
Type&Project\\
Tcl Version&\(8.7\)\\
State&Draft\\
Vote&Pending\\
Version&\tipversion$Revision: 1.6 $\\
Keywords&Tcl, platform integration, i18n\\
Post History&\\
\hline\end{tabularx}\end{center}
\thispagestyle{empty}\pagestyle{empty}
\begin{tipabstract}

The default panic proc on Windows console applications writes the message in UTF-8 to stderr. Unfortunately, the Windows console normally does not have UTF-8 as code page but some single-byte code page like CP1252. When using characters outside the ASCII range, that does not give the expected output in the console. This TIP proposes to add a new Console panic proc to the stub library, and modify the Tcl\_Main() macro to use it.
\end{tipabstract}
\tableofcontents\setcounter{page}{0}\clearpage\pagestyle{plain}

\section{Rationale}

Many parts of Tcl are initernationalized in Tcl 8.6: The command line handling, and the communication with all Win32 API functions. But the Panic proc has --- so far --- not been modified accordingly for Windows console applications, even though win32 has a suitable API to do so.

On Windows, there actually are two different panic procs, one for GUI applications and one for console applications, but external embedders don't have an API for deciding which one should be used other than provide their own. This TIP can finally do that: The call \textit{Tcl\_SetPanicProc(Tcl\_ConsolePanic)} will initialize the Tcl subsystem for Console applications, while \textit{Tcl\_SetPanicProc(NULL)} will continue to use the default.

Making things worse, stderr is implemented by the C runtime, (msvcrt??.dll) but if a application is embedding or dynamically loading tcl.dll then the runtime of the embedder might be different from tcl.dll/tclsh.exe's runtime. The embedder providing the panic proc gives the highest chance that panic messages arrive in the same runtime as the embedder. For tclsh.exe this makes no difference.

\section{Proposed Change}

A new function \textit{Tcl\_ConsolePanic} is added to the stub library on Windows and Cygwin, which can be installed by embedding application as panic proc. The full signature is:

\begin{quote}
EXTERN void \textbf{Tcl\_ConsolePanic}( const char *\textit{format} ...);
\end{quote}

On other platforms than Windows or Cygwin, \textit{Tcl\_ConsolePanic} is a macro equivalent to NULL, on those platforms Tcl\_SetPanicProc(Tcl\_ConsolePanic) has the effect of resetting the panic proc to the platform's default.

This function is meant to be used for Win32 or Cygwin console applications, and can deliver the message in 3 possible ways

* If a (Windows) debugger is running, the message is sent there.

* If stderr is connected to a Windows console, the message is sent there (Windows only).

* Otherwise, the UTF-8 BOM (3 bytes) is written followed by the unmodified message (assumed to be in UTF-8).

The function \textit{Tcl\_ConsolePanic} does not assume any locale, does not allocate memory, neither does it make any assumptions on the initialized state of Tcl. This makes Tcl\_Panic work fine even in the final stage of a Tcl\_Finalize() call. If a Win32 Unicode API is available for the desired output, \textit{Tcl\_ConsolePanic} will do at most an UTF-8 to Unicode conversion using the Win32 function MultiByteToWideChar().

The maximum number of (unicode) characters that is written is 26000, as that is the maximum that WriteConsoleW() can handle in a single call. See: [\url{https://connect.microsoft.com/VisualStudio/feedback/details/635230}] If the message is longer than that, the string is truncated and three dots appended to it. If the message is sent to a character device, the UTF-8 BOM is prepended.

The function is available from the stub library, in order to bring the responsibility for correct linking to the embedding application, in stead of Tcl. In case of tclsh.exe, this makes no difference.

\section{Reference Implementation}

A reference implementation is available in the \textbf{win-console-panic} branch. [\url{https://core.tcl.tk/tcl/info/00a17823f0}]

\section{Copyright}

This document has been placed in the public domain.

\section{Colophon}

\textit{TIP AutoGenerator --- written by Donal K. Fellows}
\end{document}
