@y
itself will get a new section number.
@^system dependencies@>
@ @<Declare procedures for Press output@>=
@<Declare external procedures for Press output@>
@<Declare extension-related procedures for Press output@>
@<Declare hlist←press←out@>
@<Declare vlist←press←out@>
@ The actual work of writing the Press file is done by the SirPress
package in Cedar. The following procedures provide access to
this package from Pascal. The final function is a little different:
its job it to provide access to our procedures from Cedar.
@<Declare external procedures for Press output@>=
function get←pype𡤌ode(f: internal𡤏ont←number; at←size←in←hnm:integer): cedar←nat;
external;
procedure press←set𡤏ont(c: cedar←nat); external;
procedure press←show𡤌har(c: quarterword); external;
procedure press←set←x(x: scaled); external;
procedure press←set←y(y: scaled); external;
procedure press←show←rule(xstart, ystart, xlen, ylen: scaled); external;
procedure flush←pype; external;
procedure press←write←page; external;
procedure press𡤌lose𡤏ile; external;
@ The procedure hlist←press←out is very similar to hlist←out. Note that
hlist←press←out makes no use of dvi←h, dvi←v, or cur←s. Instead, we make
use of the global booleans press←h←ok; if we are pyping, this
boolean tells us that there is no need to do a PipePosition before the
next PipeChar.
We shall first add a macro definition for the number of micas in
11 inches, since Press has it's vertical axis running up instead of down.
Also, a macro for the number of hectonanometers (meters*e^-7) in 11
inches, since sometimes we will be computing in them. They correspond
to SirPress.unit=100.
In addition, the origin of the DVI page is actually shifted by one inch in
both h and v. We also add macros for these distances.
@d page←height←in←mica==27940 {micas in 11 inches}
@d page←height←in←hnm==2794000 {hnm in 11 inches}
@d h←marg←in←mica==2540
@d h←marg←in←hnm==254000
@d v←marg←in←mica==2540
@d v←marg←in←hnm==254000
@<Declare hlist←press←out@>=
procedure hlist←press←out; {output an |hlist←node| box}
label reswitch, move←past, fin←rule, next←p;
var base←line: scaled; {the baseline coordinate for this box}
@!base←in←mica: scaled; {baseline in micas}
@!leftge: scaled; {the left coordinate for this box}
@!save←h,@!save←v: scaled; {still used in leaders calculations}
@!this𡤋ox: pointer; {pointer to containing box}
@!g←order: glue←ord; {applicable order of infinity for glue}
@!g←sign: normal..shrinking; {selects type of glue}
@!p:pointer; {current position in the hlist}
@!leader𡤋ox:pointer; {the leader box being replicated}
@!leader←wd:scaled; {width of leader box being replicated}
@!lx:scaled; {extra space between leader boxes}
@!outer𡤍oing←leaders:boolean; {were we doing leaders?}
@!edge:scaled; {left edge of sub-box, or right edge of leader space}
begin this𡤋ox:=temp←ptr; g←order:=glue←order(this𡤋ox);
g←sign:=glue←sign(this𡤋ox); p:=list←ptr(this𡤋ox);
base←line:=cur←v; leftge:=cur←h;
base←in←mica:=page←height←in←mica - v←marg←in←mica
- x←over←n(xn←over𡤍(base←line, mag, 18647),100);
while p<>null do @<Press: Output node |p| for |hlist←press←out| and move to the
next node, maintaining the condition |cur←v=base←line|@>;
end;
@ @<Press: Output node |p| for |hlist←press←out| ...@>=
reswitch: if is𡤌har←node(p) then
begin press←set←y(base←in←mica);
f:=font(p);
if f<>dvi𡤏 then @<Press: Change font |dvi𡤏| to |f|@>;
press←set←x(h←marg←in←mica + x←over←n(xn←over𡤍(cur←h, mag, 18647),100));
repeat
c:=character(p);
press←show𡤌har(c);
cur←h:=cur←h+char←width(f)(char←info(f)(c));
p:=link(p);
until (not is𡤌har←node(p))or(font(p)<>dvi𡤏);
end
else @<Press: Output the non-|char←node| |p| for |hlist←press←out|
and move to the next node@>
@ @<Press: Change font |dvi𡤏| to |f|@>=
begin if not font←used[f] then
begin
font←pype𡤌ode[f]:=get←pype𡤌ode(f, xn←over𡤍(font←size[f],mag,18647));
font←used[f]:=true;
end;
press←set𡤏ont(font←pype𡤌ode[f]);
dvi𡤏:=f;
end
@ @<Press: Output the non-|char←node| |p| for |hlist←press←out| ...@>=
begin case type(p) of
hlist←node,vlist←node:@<Press: Output a box in an hlist@>;
rule←node: begin rule←ht:=height(p); rule𡤍p:=depth(p); rule←wd:=width(p);
goto fin←rule;
end;
whatsit←node: @<Press: Output the whatsit node |p| in an hlist@>;
glue←node: @<Press: Move right or output leaders@>;
kern←node,math←node:cur←h:=cur←h+width(p);
ligature←node: @<Make node |p| look like a |char←node| and |goto reswitch|@>;
othercases do←nothing
endcases;@/
goto next←p;
fin←rule: @<Press: Output a rule in an hlist@>;
move←past: cur←h:=cur←h+rule←wd;
next←p:p:=link(p);
end
@ @<Press: Output a box in an hlist@>=
if list←ptr(p)=null then cur←h:=cur←h+width(p)
else begin cur←v:=base←line+shift𡤊mount(p); {shift the box down}
temp←ptr:=p; edge:=cur←h;
if type(p)=vlist←node then vlist←press←out@+else hlist←press←out;
cur←h:=edge+width(p); cur←v:=base←line;
end
@ @<Press: Output a rule in an hlist@>=
if is←running(rule←ht) then rule←ht:=height(this𡤋ox);
if is←running(rule𡤍p) then rule𡤍p:=depth(this𡤋ox);
rule←ht:=rule←ht+rule𡤍p; {this is the rule thickness}
if (rule←ht>0)and(rule←wd>0) then {we don't output empty rules}
begin press←show←rule(h←marg←in←hnm + xn←over𡤍(cur←h,mag,18647),
page←height←in←hnm - v←marg←in←hnm
- xn←over𡤍(base←line+rule𡤍p,mag,18647),
xn←over𡤍(rule←wd,mag,18647),
xn←over𡤍(rule←ht,mag,18647));
cur←v:=base←line;
end
@ @<Press: Move right or output leaders@>=
begin g:=glue←ptr(p); rule←wd:=width(g);
if g←sign<>normal then
begin if g←sign=stretching then
begin if stretch←order(g)=g←order then
rule←wd:=rule←wd+round(float(glue←set(this𡤋ox))*stretch(g));
@^real multiplication@>
end
else begin if shrink←order(g)=g←order then
rule←wd:=rule←wd-round(float(glue←set(this𡤋ox))*shrink(g));
end;
end;
if subtype(p)>=a←leaders then
@<Press: Output leaders in an hlist, |goto fin←rule| if a rule
or to |next←p| if done@>;
goto move←past;
end
@ @<Press: Output leaders in an hlist...@>=
begin leader𡤋ox:=leader←ptr(p);
if type(leader𡤋ox)=rule←node then
begin rule←ht:=height(leader𡤋ox); rule𡤍p:=depth(leader𡤋ox);
goto fin←rule;
end;
leader←wd:=width(leader𡤋ox);
if (leader←wd>0)and(rule←wd>0) then
begin edge:=cur←h+rule←wd; lx:=0;
@<Let |cur←h| be the position of the first box, and set |leader←wd+lx|
to the spacing between corresponding parts of boxes@>;
while cur←h+leader←wd<=edge do
@<Press: Output a leader box at |cur←h|,
then advance |cur←h| by |leader←wd+lx|@>;
cur←h:=edge; goto next←p;
end;
end
@ @<Press: Output a leader box at |cur←h|, ...@>=
begin cur←v:=base←line+shift𡤊mount(leader𡤋ox); save←v:=cur←v;@/
save←h:=cur←h; temp←ptr:=leader𡤋ox;
outer𡤍oing←leaders:=doing←leaders; doing←leaders:=true;
if type(leader𡤋ox)=vlist←node then vlist←press←out@+else hlist←press←out;
doing←leaders:=outer𡤍oing←leaders;
cur←v:=save←v;
cur←h:=save←h+leader←wd+lx;
end
@ @<Declare vlist←press←out@>=
procedure vlist←press←out; {output a |vlist←node| box}
label move←past, fin←rule, next←p;
var leftge: scaled; {the left coordinate for this box}
@!topge: scaled; {the top coordinate for this box}
@!save←h,@!save←v: scaled; {what |dvi←h| and |dvi←v| should pop to}
@!this𡤋ox: pointer; {pointer to containing box}
@!g←order: glue←ord; {applicable order of infinity for glue}
@!g←sign: normal..shrinking; {selects type of glue}
@!p:pointer; {current position in the vlist}
@!leader𡤋ox:pointer; {the leader box being replicated}
@!leader←ht:scaled; {height of leader box being replicated}
@!lx:scaled; {extra space between leader boxes}
@!outer𡤍oing←leaders:boolean; {were we doing leaders?}
@!edge:scaled; {bottom boundary of leader space}
begin this𡤋ox:=temp←ptr; g←order:=glue←order(this𡤋ox);
g←sign:=glue←sign(this𡤋ox); p:=list←ptr(this𡤋ox);
leftge:=cur←h; cur←v:=cur←v-height(this𡤋ox);
topge:=cur←v;
while p<>null do @<Press: Output node |p| for |vlist←press←out| and move
to the next node, maintaining the condition |cur←h=leftge|@>;
end;
@ @<Press: Output node |p| for |vlist←press←out|...@>=
begin if is𡤌har←node(p) then confusion("vlistout")
@:this can't happen vlistout}{\quad vlistout@>
else @<Press: Output the non-|char←node| |p| for |vlist←press←out|@>;
next←p:p:=link(p);
end
@ @<Press: Output the non-|char←node| |p| for |vlist←press←out|@>=
begin case type(p) of
hlist←node,vlist←node:@<Press: Output a box in a vlist@>;
rule←node: begin rule←ht:=height(p); rule𡤍p:=depth(p); rule←wd:=width(p);
goto fin←rule;
end;
whatsit←node: @<Press: Output the whatsit node |p| in a vlist@>;
glue←node: @<Press: Move down or output leaders@>;
kern←node:cur←v:=cur←v+width(p);
othercases do←nothing
endcases;@/
goto next←p;
fin←rule: @<Press: Output a rule in a vlist, |goto next←p|@>;
move←past: cur←v:=cur←v+rule←ht;
end
@ @<Press: Output a box in a vlist@>=
if list←ptr(p)=null then cur←v:=cur←v+height(p)+depth(p)
else begin cur←v:=cur←v+height(p);
save←v:=cur←v;
cur←h:=leftge+shift𡤊mount(p); {shift the box right}
temp←ptr:=p;
if type(p)=vlist←node then vlist←press←out@+else hlist←press←out;
cur←v:=save←v+depth(p); cur←h:=leftge;
end
@ @<Press: Output a rule in a vlist...@>=
if is←running(rule←wd) then rule←wd:=width(this𡤋ox);
rule←ht:=rule←ht+rule𡤍p; {this is the rule thickness}
cur←v:=cur←v+rule←ht;
if (rule←ht>0)and(rule←wd>0) then {we don't output empty rules}
begin press←show←rule(h←marg←in←hnm + xn←over𡤍(cur←h,mag,18647),
page←height←in←hnm - v←marg←in←hnm
- xn←over𡤍(cur←v,mag,18647),
xn←over𡤍(rule←wd,mag,18647),
xn←over𡤍(rule←ht,mag,18647));
end;
goto next←p
@ @<Press: Move down or output leaders@>=
begin g:=glue←ptr(p); rule←ht:=width(g);
if g←sign<>normal then
begin if g←sign=stretching then
begin if stretch←order(g)=g←order then
rule←ht:=rule←ht+round(float(glue←set(this𡤋ox))*stretch(g));
@^real multiplication@>
end
else begin if shrink←order(g)=g←order then
rule←ht:=rule←ht-round(float(glue←set(this𡤋ox))*shrink(g));
end;
end;
if subtype(p)>=a←leaders then
@<Press: Output leaders in a vlist, |goto fin←rule| if a rule
or to |next←p| if done@>;
goto move←past;
end
@ @<Press: Output leaders in a vlist...@>=
begin leader𡤋ox:=leader←ptr(p);
if type(leader𡤋ox)=rule←node then
begin rule←wd:=width(leader𡤋ox); rule𡤍p:=0;
goto fin←rule;
end;
leader←ht:=height(leader𡤋ox)+depth(leader𡤋ox);
if (leader←ht>0)and(rule←ht>0) then
begin edge:=cur←v+rule←ht; lx:=0;
@<Let |cur←v| be the position of the first box, and set |leader←ht+lx|
to the spacing between corresponding parts of boxes@>;
while cur←v+leader←ht<=edge do
@<Press: Output a leader box at |cur←v|,
then advance |cur←v| by |leader←ht+lx|@>;
cur←v:=edge; goto next←p;
end;
end
@ @<Press: Output a leader box at |cur←v|, ...@>=
begin cur←h:=leftge+shift𡤊mount(leader𡤋ox); save←h:=cur←h;@/
cur←v:=cur←v+height(leader𡤋ox); save←v:=cur←v;
temp←ptr:=leader𡤋ox;
outer𡤍oing←leaders:=doing←leaders; doing←leaders:=true;
if type(leader𡤋ox)=vlist←node then vlist←press←out@+else hlist←press←out;
doing←leaders:=outer𡤍oing←leaders;
cur←h:=save←h;
cur←v:=save←v-height(leader𡤋ox)+leader←ht+lx;
end
@ @<Declare extension-related procedures for Press output@>=
procedure press←out←what(@!p:pointer);
begin case subtype(p) of
open←node,write←node,close←node:out←what(p);
special←node:do←nothing; {specials not implemented for Press output}
othercases confusion("ext4")
@:this can't happen ext4}{\quad ext4@>
endcases;
end;
@ @<Press: Output the whatsit node |p| in an hlist@>=
press←out←what(p)
@ @<Press: Output the whatsit node |p| in a vlist@>=
press←out←what(p)
@ We want to refer to the type of SirPress font codes from with Pascal, so we
do the following.
@<Types...@>=
@!cedar←nat=0..32767;
@ Here, finally, are the external procedure declarations.
@<External procedure declarations for things implemented directly in Cedar@>=
procedure reset←term←in(var f: alpha𡤏ile); external;
{set up for input from terminal}
procedure rewrite←term←out(var f: alpha𡤏ile); external;
{set up for output to terminal}
function profile𡤊sks𡤏or←press: boolean; external;
function press←open←out: boolean; external;
procedure read←the𡤌lock(var ttime,dday,mmonth,yyear:integer); external;
function file←get←pos(var f: alpha𡤏ile):integer; external; {return character count}
procedure set←pool←name; external;
procedure read←profile𡤏or𡤍irectories; external;
procedure set←normal←priority; external;
procedure setkground←priority; external;
function stuff←on𡤌md←line:integer; external;