home *** CD-ROM | disk | FTP | other *** search
-
- {chapter7.pas}
-
- {
- copyright (c) 1981
- by: bell telephone laboratories, inc. and
- whitesmith's ltd.,
-
- this software is derived from the book
- "software tools in pascal", by
- brian w. kernighan and p. j. plauger
- addison-wesley, 1981
- isbn 0-201-10342-7
-
- right is hereby granted to freely distribute or duplicate this
- software, providing distribution or duplication is not for profit
- or other commercial gain and that this copyright notice remains
- intact.
- }
-
- procedure format;
- const
- cmd=period;
- pagenum=sharp;
- pagewidth=60;
- pagelen=66;
- huge=10000;
- type
- cmdtype=(bp,br,ce,fi,fo,he,ind,ls,nf,pl,
- rm,sp,ti,ul,unknown);
- var
- curpage,newpage,lineno:integer;
- plval,m1val,m2val,m3val,m4val:integer;
- bottom:integer;
- header,footer:xstring;
-
- fill:boolean;
- lsval,spval,inval,rmval,tival,ceval,ulval:integer;
-
- outp,outw,outwds:integer;
- outbuf:xstring;
- dir:0..1;
- inbuf:xstring;
-
- procedure skipbl(var s:xstring;var i:integer);
- begin
- while(s[i]=blank) or(s[i]=tab)do
- i:=i+1
- end;
-
- function getval(var buf:xstring;var argtype:integer):integer;
- var
- i:integer;
- begin
- i:=1;
- while(not(buf[i]in[blank,tab,newline]))do
- i:=i+1;
- skipbl(buf,i);
- argtype:=buf[i];
- if(argtype=plus) or (argtype=minus) then
- i:=i+1;
- getval:=ctoi(buf,i)
- end;
-
- procedure setparam(var param:integer;val,argtype,defval,minval,maxval:
- integer);
- begin
- if(argtype=newline)then
- param:=defval
- else if (argtype=plus)then
- param:=param+val
- else if(argtype=minus) then
- param:=param-val
- else param:=val;
- param:=min(param,maxval);
- param:=max(param,minval)
- end;
-
- procedure skip(n:integer);
- var i:integer;
- begin
- for i:=1 to n do
- putc(newline)
- end;
-
- procedure puttl(var buf:xstring;pageno:integer);
- var i:integer;
- begin
- for i:=1 to xlength(buf) do
- if(buf[i]=pagenum) then
- putdec(pageno,1)
- else
- putc(buf[i])
- end;
-
- procedure putfoot;
- begin
- skip(m3val);
- if(m4val>0) then begin
- puttl(footer,curpage);
- skip(m4val-1)
- end
- end;
-
- procedure puthead;
- begin
- curpage:=newpage;
- newpage:=newpage+1;
- if(m1val>0)then begin
- skip(m1val-1);
- puttl(header,curpage)
- end;
- skip(m2val);
- lineno:=m1val+m2val+1
- end;
-
- procedure put(var buf:xstring);
- var
- i:integer;
- begin
- if(lineno<=0) or(lineno>bottom) then
- puthead;
- for i:=1 to inval+tival do
- putc(blank);
- tival:=0;
- putstr(buf,stdout);
- skip(min(lsval-1,bottom-lineno));
- lineno:=lineno+lsval;
- if(lineno>bottom)then putfoot
- end;
-
-
- procedure break;
- begin
- if(outp>0) then begin
- outbuf[outp]:=newline;
- outbuf[outp+1]:=endstr;
- put(outbuf)
- end;
- outp:=0;
- outw:=0;
- outwds:=0
- end;
-
- function getword(var s:xstring;i:integer;
- var out:xstring):integer;
- var
- j:integer;
- begin
- while(s[i] in [blank,tab,newline]) do
- i:=i+1;
- j:=1;
- while(not (s[i] in [endstr,blank,tab,newline])) do begin
- out[j]:=s[i];
- i:=i+1;
- j:=j+1
- end;
- out[j]:=endstr;
- if(s[i]=endstr) then
- getword:=0
- else
- getword:=i
- end;
-
- procedure leadbl(var buf:xstring);
- var i,j:integer;
- begin
- break;
- i:=1;
- while(buf[i]=blank) do
- i:=i+1;
- if(buf[i]<>newline) then
- tival:=tival+i-1;
- for j:=i to xlength(buf)+1 do
- buf[j-i+1]:=buf[j]
- end;
-
- procedure gettl(var buf,ttl:xstring);
- var
- i:integer;
- begin
- i:=1;
- while(not(buf[i]in[blank,tab,newline]))do
- i:=i+1;
- skipbl(buf,i);
- if(buf[i]=squote) or(buf[i]=dquote)then
- i:=i+1;
- scopy(buf,i,ttl,1)
- end;
-
- procedure space(n:integer);
- begin
- break;
- if (lineno<=bottom) then begin
- if(lineno<=0)then
- puthead;
- skip(min(n,bottom+1-lineno));
- lineno:=lineno+n;
- if(lineno>bottom) then
- putfoot
- end
- end;
-
- procedure page;
- begin
- break;
- if(lineno>0) and (lineno<=bottom) then begin
- skip(bottom+1-lineno);putfoot
- end;
- lineno:=0
- end;
-
- function width(var buf:xstring):integer;
- var
- i,w:integer;
- begin
- w:=0;
- i:=1;
- while(buf[i]<>endstr) do begin
- if (buf[i] = backspace) then
- w:=w-1
- else if (buf[i]<>newline) then
- w:=w+1;i:=i+1
- end;
- width:=w
- end;
-
- procedure spread(var buf:xstring;
- outp,nextra,outwds:integer);
- var
- i,j,nb,nholes:integer;
- begin
- if(nextra>0) and (outwds>1) then begin
- dir:=1-dir;
- nholes:=outwds-1;
- i:=outp-1;
- j:=min(maxstr-2,i+nextra);
- while(i<j) do begin
- buf[j]:=buf[i];
- if(buf[i]=blank) then begin
- if(dir=0) then
- nb:=(nextra-1) div nholes +1
- else nb:=nextra div nholes;
- nextra:=nextra - nb;
- nholes:=nholes-1;
- while(nb>0) do begin
- j:=j-1;
- buf[j]:=blank;
- nb:=nb-1
- end
- end;
- i:=i-1;
- j:=j-1
- end
- end
- end;
-
- procedure putword(var wordbuf:xstring);
- var
- last,llval,nextra,w:integer;
- begin
- w:=width(wordbuf);
- last:=xlength(wordbuf)+outp+1;
- llval:=rmval-tival-inval;
- if(outp>0)
- and ((outw+w>llval) or (last >=maxstr)) then begin
- last:=last-outp;
- nextra:=llval-outw+1;
- if(nextra >0) and(outwds>1) then begin
- spread(outbuf,outp,nextra,outwds);
- outp:=outp+nextra
- end;
- break
- end;
- scopy(wordbuf,1,outbuf,outp+1);
- outp:=last;
- outbuf[outp]:=blank;
- outw:=outw+w+1;
- outwds:=outwds+1
- end;
-
- procedure center(var buf:xstring);
- begin
- tival:=max((rmval+tival-width(buf)) div 2,0)
- end;
-
- procedure underln (var buf:xstring;size:integer);
- var
- i,j:integer;
- tbuf:xstring;
- begin
- j:=1;
- i:=1;
- while(buf[i]<>newline) and (j<size-1)do begin
- if(isalphanum(buf[i])) then begin
- tbuf[j]:=underline;
- tbuf[j+1]:=backspace;
- j:=j+2
- end;
- tbuf[j]:=buf[i];
- j:=j+1;
- i:=i+1
- end;
- tbuf[j]:=newline;
- tbuf[j+1]:=endstr;
- scopy(tbuf,1,buf,1)
- end;
-
- procedure text(var inbuf:xstring);
- var
- wordbuf:xstring;
- i:integer;
- begin
- if(inbuf[1]=blank) or (inbuf[1]=newline) then
- leadbl(inbuf);
- if(ulval>0) then begin
- underln(inbuf,maxstr);
- ulval:=ulval-1
- end;
- if(ceval>0)then begin
- center(inbuf);
- put(inbuf);
- ceval:=ceval-1
- end
- else if (inbuf[1]=newline)then
- put(inbuf)
- else if(not fill) then
- put(inbuf)
- else begin
- i:=1;
- repeat
- i:=getword(inbuf,i,wordbuf);
- if(i>0)then
- putword(wordbuf)
- until(i=0)
- end
-
- end;
-
-
- procedure initfmt;
- begin
- fill:=true;
- dir:=0;
- inval:=0;
- rmval:=pagewidth;
- tival:=0;
- lsval:=1;
- spval:=0;
- ceval:=0;
- ulval:=0;
- lineno:=0;
- curpage:=0;
- newpage:=1;
- plval:=pagelen;
- m1val:=3;m2val:=2;m3val:=2;m4val:=3;
- bottom:=plval-m3val-m4val;
- header[1]:=newline;
- header[2]:=endstr;
- footer[1]:=newline;
- footer[2]:=endstr;
- outp:=0;
- outw:=0;
- outwds:=0
- end;
-
- function getcmd(var buf:xstring):cmdtype;
- var
- cmd:packed array[1..2] of char;
- begin
- cmd[1]:=chr(buf[2]);
- cmd[2]:=chr(buf[3]);
- if(cmd='fi')then getcmd:=fi
- else if (cmd='nf')then getcmd:=nf
- else if (cmd='br')then getcmd:=br
- else if (cmd='ls')then getcmd:=ls
- else if (cmd='bp')then getcmd:=bp
- else if (cmd='sp')then getcmd:=sp
- else if (cmd='in')then getcmd:=ind
- else if (cmd='rm')then getcmd:=rm
- else if (cmd='ce')then getcmd:=ce
- else if (cmd='ti')then getcmd:=ti
- else if (cmd='ul')then getcmd:=ul
- else if (cmd='he') then getcmd:=he
- else if (cmd='fo') then getcmd:=fo
- else if (cmd='pl') then getcmd:=pl
- else getcmd:=unknown
- end;
-
- procedure command(var buf:xstring);
- var cmd:cmdtype;
- argtype,spval,val:integer;
- begin
- cmd:=getcmd(buf);
- if(cmd<>unknown)then
- val:=getval(buf,argtype);
- case cmd of
- fi:begin
- break;
- fill:=true end;
- nf:begin break;
- fill:=false end;
- br:break;
- ls:setparam(lsval,val,argtype,1,1,huge);
- ce:begin break;
- setparam(ceval,val,argtype,1,0,huge) end;
- ul:setparam(ulval,val,argtype,1,0,huge);
- he:gettl(buf,header);
- fo:gettl(buf,footer);
- bp:begin page;
- setparam(curpage,val,argtype,curpage+1,-huge,huge);
- newpage:=curpage end;
- sp:begin
- setparam(spval,val,argtype,1,0,huge);
- space(spval)
- end;
- ind:setparam(inval,val,argtype,0,0,rmval-1);
- rm:setparam(inval,val,argtype,pagewidth,
- inval+tival+1,huge);
- ti:begin break;
- setparam(tival,val,argtype,0,-huge,rmval) end;
- pl:begin
- setparam(plval,val,argtype,pagelen,
- m1val+m2val+m3val+m4val+1,huge);
- bottom:=plval-m3val-m4val end;
- unknown:
- end
- end;
-
-
-
-
- begin
-
- initfmt;
- while(getline(inbuf,stdin,maxstr))do
- if(inbuf[1]=cmd) then
- command(inbuf)
- else
- text(inbuf);
- page
- end;