Does anything besides ConTeXt use dvipos?
Googling for the specials that dvipos parses, such as pos:pxywhd,
produces one hit and it's on the ntg-context list. So it's a safe bet
that ConTeXt is the only user.
If not, then Sanjoys patch that simply adds "sp" after each number
seems fine to me.
It's necessary but not sufficient, since dvipos still won't be able to
parse the specials that (Con)TeX(t) writes because those are in pt, and
have 'pt' appended. Therefore the second patch that I sent is also
needed. It's not perfect since it doesn't fix sscanfing 'list' in
dvicore.c:do_pos_special().
But I just figured out what list's format should be and what to do about
it. Assuming again that ConTeXt is the only user of those specials, the
relevant code is from core-pos.tex (line 525ff):
\def\doregisterparoptions
{\doglobal\increment\parposcounter
\begingroup
\leftskip 1\leftskip
\rightskip1\rightskip
\setpositiondataplus
{p:\parposcounter}% % identifier
{\the\zeropoint}%
{\the\strutht}%
{\the\strutdp}%
{\the\hsize ,% 1
\the\leftskip ,% 2
\the\rightskip ,% 3
\the\hangindent,% 4
\the\hangafter ,% 5 (num)
\the\parindent }% 6
%\normalhbox{\registerparsymbol}%
\registerparsymbol
\endgroup}
If list needs to be extracted from the pos:pxyplus special, which is the
only one that uses it, its format will be like:
469.75499pt,0.0pt,0.0pt,0.0pt,1,20.0pt
That string needs %fpt,%fpt,%fpt,%fpt,%ld,%fpt as its scanf format.
do_pos_special() instead sscanf's list as %ld, which will pick up just
the 469. So here is the third patch (and the dvicore.c with all three
patches is attached).
I tested the result and it still works with pos:pxywhd, and I compiled
it with -Wformat=2 just to make sure I hadn't screwed up a sscanf or
fprintf format string. But I don't have a dvi file that uses
pos:pxyplus, so I can't test the new code path.
Hans,
Could you make a minimal .tex file that would use pos:pxyplus?
-Sanjoy
`A nation of slaves is always prepared to applaud the clemency of their
master who, in the abuse of absolute power, does not proceed to the
last extremes of injustice and oppression.' (Gibbon)
changeset: 3:36f5c3fd455c
tag: tip
user: Sanjoy Mahajan
date: Sun Jan 07 14:34:34 2007 -0500
summary: do_pos_special(): 'list' needs to be parsed as a structure
diff -r f30b6ea9f33e -r 36f5c3fd455c dvicore.c
--- a/dvicore.c Sat Jan 06 21:45:10 2007 -0500
+++ b/dvicore.c Sun Jan 07 14:34:34 2007 -0500
@@ -896,7 +896,15 @@ static void do_pos_special (unsigned cha
static void do_pos_special (unsigned char *buffer, SIGNED_QUAD buffer_len)
{
unsigned char *cmd, *tag, *p;
- SIGNED_QUAD x, y, w, h, d, list;
+ SIGNED_QUAD x, y, w, h, d;
+ double w_pt, h_pt, d_pt; /* in pt */
+ int parsed = 0; /* how many conversions the sscanf managed */
+
+ struct /* see \doregisterparoptions in ConTeXt's core-pos.tex */
+ {
+ double hsize, leftskip, rightskip, hangindent, parindent;
+ SIGNED_QUAD hangafter;
+ } list;
for (p = buffer; p - buffer < buffer_len && isspace(*p); p++)
; /* skip white chars */
@@ -919,13 +927,15 @@ static void do_pos_special (unsigned cha
; /* skip white chars */
if (p - buffer < buffer_len)
{
- float w_f, h_f, d_f; /* in pt */
- /* what the hell is list? */
- sscanf(p, "%fpt %fpt %fpt %ld", &w_f, &h_f, &d_f, &list);
- /* convert to sp. Forget about rounding (add 0.5 if you want it). */
- w = w_f * 65536;
- h = h_f * 65536;
- d = d_f * 65536;
+ /* hangafter is a number, not a dimension, hence its %ld */
+ parsed = sscanf(p, "%lfpt %lfpt %lfpt %lfpt,%lfpt,%lfpt,%lfpt,%ld,%lfpt",
+ &w_pt, &h_pt, &d_pt,
+ &list.hsize, &list.leftskip, &list.rightskip,
+ &list.hangindent, &list.hangafter, &list.parindent);
+ /* convert pt to sp. Forget about rounding (add 0.5 if you want it). */
+ w = w_pt * 65536;
+ h = h_pt * 65536;
+ d = d_pt * 65536;
}
x = dvi_state.h + denominator / 100;
@@ -935,8 +945,14 @@ static void do_pos_special (unsigned cha
fprintf(outfp, "\\pospxy{%s}{%d}{%ldsp}{%ldsp}\n", tag, current_page, x, y);
else if (strcmp(cmd, "pos:pxywhd") == 0)
fprintf(outfp, "\\pospxywhd{%s}{%d}{%ldsp}{%ldsp}{%ldsp}{%ldsp}{%ldsp}\n", tag, current_page, x, y, w, h, d);
- else if (strcmp(cmd, "pos:pxyplus") == 0)
- fprintf(outfp, "\\pospxyplus{%s}{%d}{%ldsp}{%ldsp}{%ldsp}{%ldsp}{%ldsp}{%ld}\n", tag, current_page, x, y, w, h, d, list);
+ else if (strcmp(cmd, "pos:pxyplus") == 0) {
+ if (parsed < 9)
+ fprintf(stderr, "dvipos: only %d conversions for \\pospxyplus but 9 are needed\nBeward: Coordinates in the output may therefore be junk. Continuing anyway...", parsed);
+ fprintf(outfp, "\\pospxyplus{%s}{%d}{%ldsp}{%ldsp}{%ldsp}{%ldsp}{%ldsp}", tag, current_page, x, y, w, h, d);
+ fprintf(outfp, "{%lfpt,%lfpt,%lfpt,%lfpt,%ld,%lfpt}\n",
+ list.hsize, list.leftskip, list.rightskip,
+ list.hangindent, list.hangafter, list.parindent);
+ }
else if (strcmp(cmd, "pos:begbox") == 0)
new_bbox(tag, BOX_TYPE);
else if (strcmp(cmd, "pos:endbox") == 0)