[pdftex] \escapes and /Limits

Hartmut Henkel hartmut_henkel at gmx.de
Sat Jul 3 16:03:14 CEST 2004


On Fri, 2 Jul 2004, Karl Berry wrote:

> (I apologize in advance for not knowing enough to be sure if I really
> understand what's happening, not to mention the complexity of the
> question.)

More of the same for me.

> At the moment, I'm having texinfo.tex create destinations for outline
> entries whose names contain PostScript string escape sequences.  (\no),
> for example, that is, when interpreted, the two characters "newline" and
> "o".  (Ultimately, it calls (line 1253)
>   \pdfoutline goto name{\no}count-0{foo}
> where the \ is catcode 12.
> )
>
> The problem is that the resulting outline entry in the PDF file cannot
> be followed, i.e., clicking on it does nothing.  (Both xpdf and acrobat.)
> (In the attached pdf, go to page 2, then click on the `foo' outline
> link, and observe that nothing happens.)
>
> It appears to me that the generated PDF file may be incorrect.  With the
> attached test file, run through the attached (unreleased) texinfo.tex,
> the resulting (also attached) PDF contains:
>
>     /Names [(-1) 13 0 R (1) 4 0 R (\no) 5 0 R]
>     /Limits [(-1) (\no)]
...

Maybe, once things are interpreted as strings, the escaping should work,
after PDF reference Table 3.2, to keep the PDF file valid. But pdfTeX's
str_less_str() function, which does the sorting here, does not deal with
escaped chars at all. So before thinking (any further), i tried to let
the sorting handle also these escaped things. Below is some buggy change
file, but at least, on some input file like

\let\nno\relax
\let\nna\relax
\pdfcompresslevel=0

\pdfdest name {\nno} fit
hello on page 1
\vfill\eject

\pdfdest name {\nna} fit
hello on page 2
\vfill\eject

\pdfdest name {-1nx} fit
hello on page 3
\vfill\eject

hello on page 4
\pdfoutline goto name{\nno}count-0{jumpto page 1}
\pdfoutline goto name{\nna}count-0{jumpto page 2}
\pdfoutline goto name{-1nx}count-0{jumpto page 3}
\bye

it sorts so that

/Limits [(\nna ) (-1nx)]

and then it can be clicked. BTW, TeX-like i don't even understand why
some \nno does end up in the PDF file when it's \let \relax.

In the change file missing is octal interpretation, and the case that
the character after the backslash is not in the list, and therefore the
backslash itself should be ignored. Further if the backslash is alone at
the end of the string. All these gory cases...

Best Regards

Hartmut

P.S. maybe one should switch to the ntg-pdftex list


File tex.ch2:

@x
The following procedures sort the table of destination names
@p function str_less_str(s1, s2: str_number): boolean; {compare two strings}
var j1, j2: pool_pointer;
    l, i: integer;
begin
    j1 := str_start[s1];
    j2 := str_start[s2];
    if length(s1) < length(s2) then
        l := length(s1)
    else
        l := length(s2);
    i := 0;
    while (i < l) and (str_pool[j1 + i] = str_pool[j2 + i]) do
        incr(i);
    if ((i < l) and (str_pool[j1 + i] < str_pool[j2 + i])) or
        ((i = l) and (length(s1) < length(s2))) then
        str_less_str := true
    else
        str_less_str := false;
end;
@y ---------------------------------------------------------------------
The following procedures sort the table of destination names.
@p function get_escaped_char(j: pool_pointer; i, l: integer): integer; {interpret backslashes}
var c, s: integer;
begin
    c := str_pool[j + i + 1];
    case c of
      92: begin {backslash}
      s := 1;
      c := 92;
      end;
      110: begin {n}
      s := 1;
      c := 10;
      end;
      114: begin {r}
      s := 1;
      c := 13;
      end;
      116: begin {t}
      s := 1;
      c := 9;
      end;
      98: begin {b}
      s := 1;
      c := 8;
      end;
      102: begin {f}
      s := 1;
      c := 12;
      end;
      40: begin {(}
      s := 1;
      c := 40;
      end;
      41: begin {)}
      s := 1;
      c := 41;
      end;
    othercases begin
      s := 0;
    end
    endcases;
    get_escaped_char := 4 * c + s; {mod 4: range 0...3, max. for octal \ooo}
end;

function str_less_str(s1, s2: str_number): boolean; {compare two strings}
var j1, j2: pool_pointer;
    i1, i2: integer;
    l1, l2: integer;
    c1, c2: integer;
begin
    j1 := str_start[s1];
    j2 := str_start[s2];
    l1 := length(s1);
    l2 := length(s2);
    i1 := 0;
    i2 := 0;
    c1 := 0;
    c2 := 0;
    while (i1 < l1) and (i2 < l2) and (c1 = c2) do begin
        c1 := str_pool[j1 + i1];
        c2 := str_pool[j2 + i2];
        if str_pool[j1 + i1] = 92 then begin {backslash}
            c1 := get_escaped_char(j1, i1, l1);
            i1 := i1 + c1 mod 4;
            c1 := c1 div 4;
        end;
        i1 := i1 + 1;
        if str_pool[j2 + i2] = 92 then begin
            c2 := get_escaped_char(j2, i2, l2);
            i2 := i2 + c2 mod 4;
            c2 := c2 div 4;
        end;
        i2 := i2 + 1;
    end;
    if (c1 < c2) or
        ((c1 = c2) and (i1 = l1) and (i2 < l2)) then
        str_less_str := true
    else
        str_less_str := false;
end;
@z



More information about the pdftex mailing list