{**********************************************************************} {* APMTEL Client *} {* Andrew Ness 1988 CS4 project *} {* Modded version - see mod list below *} {* *} {* Version 1.2 20 Jun 1988 *} {**********************************************************************} ! Control sub-module ! ! ! USER INTERFACE TO THE APMTEL SERVER ON FILESTORE D ! ! History: ! ! 20/2/88 Initial naive unfriendly version written to test SERVER ! 22/2/88 Re-write and re-structure of the code for ease of maintainance ! 3/3/88 Inclusion of REGION untility to allow access to caching mechanism ! 3/3/88 Addition of cache structure access thru insert page to place a ! file into a cache database ! So far this cache is write-only, but I am working on the code to ! allow reading the cache ! 8/3/88 The cache is now read-write ! 10/5/88 Inclusion of Channel 5 - EUCSD pages ! 16/5/88 cache only indication if server is not running ! 17/5/88 Addition of design module ! 17/5/88 Addition of termlib control for user interface ! %option "-low-nons" %include "APMTEL:ins_pg3.inc" %include "inc:fs.imp" %include "inc:fsutil.imp" %include "inc:util.imp" %include "inc:vtlib.imp" %include "files.inc" %include "level1:graphinc.imp" %constinteger MaxR=23, MaxC=39, escape = 27, keypad = 79, cursors = 91, uparrow = 65, downarrow = 66, rightarrow = 67, leftarrow = 68, home = 72, enter = 77, pf1 = 80, pf2 = 81, pf3 = 82, pf4 = 83, padcomma = 108, padminus = 109, paddot = 110, pad0 = 112, pad1=113, pad7=119, pad8=120, pad9=121, delete = 127 %externalroutinespec show comments %constbyte default mode = 0, graphics mode = 1, held mode = 2, double height mask = 4, separated graphics mask = 8, conceal = 16 %constinteger hold graphics = 30, release graphics = 31, new background = 29, black background = 28, double height = 13, normal height = 12, contiguous graphics = 25, separated graphics = 26 %constinteger text = 0, graphics = 1, sep graphics = 2, double text = 3, double graphics = 4, double sep graphics = 5 %begin %integer font w, font h %ownbytearray page(0:31,0:MaxC)= ' '(*) %ownbytearray dh(0:MaxR) %ownintegerarray font store (0 : 5) = 0(*) %owninteger current font=text %ownintegerarray virscreen(0:31, 0:39) = 0(*) %constinteger server station = 16_35, { Filestore D station number magic number = 16, { The magic number of the APMTEL server my port= 21, { The local port used buf size = 520, { Maximum size of the ether packet true = 1, false = 0 %integer server port, n, c, graphics flag, cache only %byte comm %integer pagestore, {100 * bytearray page(0:31,0:39) } %integer i, j, command, param, channel %string (255) filename %constinteger title row=0, menu row=2, menu col=40, error row=15, comment row=17, prompt row=menu row+8, com row=20,divider col=39 !spaceline is spaces and a bar. %conststring (40) spaceline = "| " %routine line(%integer row) vt at(row,menu col); printstring(spaceline); vt at(row, menu col) %end %routine print at line(%integer row, %string (255) text) %string (255) thistext %while text -> thistext.(snl).text %cycle vt at(row, menu col); printsymbol('|') printstring(thistext); spaces(40-length(thistext)) row=row+1 %repeat vt at(row, menu col); printsymbol('|') printstring(text); spaces(40-length(text)) %end %routine title line(%string (255) text) line(title row); printstring(text) %end %routine flag error(%string (255) text) print at line(error row, text) %end %routine flag comment 2(%string (255) text) print at line(comment row+1, text) %end %routine flag comment(%string (255) text) print at line(comment row, text) %end %routine show prompt(%string (255) text) print at line(prompt row, text) vt at(prompt row+1, menu col) %end %predicate pending read(%integer port) %integer bit bit=1< timeout*1000 %or bytes#0 %return bytes %end %integerfn server handshake(%string (255) command, %integer timeout, %bytearrayname response(0:*), %integername len) %integer t ether write(my port,charno(command,1),length(command)) t = cputime %cycle %if pending read(my port) %then %c len = ether read(my port,response(0),BUF SIZE) %and %result=0 %result=-1 %if cputime-t > timeout*1000 !! %result=1 %if testsymbol=' ' %repeat %end %predicate start talking %integer rc %string (255) command %bytearray buffer(0:1279) ether close(my port) {Make sure local port is closed ether open(my port, server station<<8) {Open connection to the SERVER command = tostring(magic number) rc=server handshake(command, 5, buffer, n); !"Hello server" ! !If the number of bytes rxd is 0, then the filestore is not up or is busy.... !so tell the user to try again later ! clear frame %if rc#0 %start flag error("Server not responding - cache only".snl. %c "Retry by attempting to force a download (menu option 2)") ! ether close(my port) %false %finish ! !Now, if the remote port number is less than 1, then the server is not running !on the filestore ! server port = buffer(0) - '0' %if server port <1 %start flag error("Server not running - cache only".snl. %c "Retry by attempting to force a download (menu option 2)") ! ether close(my port) %false %finish flag comment("Hi - APMTEL SERVER Connected") ether close(my port) ether open(my port, server station << 8 ! server port) rc=server handshake("A".current user, 5, buffer, n) cache only = false %true %end %bytefn to upper(%byte c) %if 'a' <= c <= 'z' %thenreturn c-'a'+'A' %elsereturn c %end !Routine to take teletext page/subpage from header and convert to integer. %integerfn txstoi(%integer packet) %constinteger hi=0, lo=1 %integerfn nib(%integer offset,hilo) %integer n n = byteinteger(packet+offset) %if hilo=hi %then n=n>>4 %result=n&15 %end %result = %c (((((nib(5,lo)*10+nib(0,hi))*10+nib(0,lo))*10+nib(1,hi))*10+%c nib(1,lo))*10+nib(2,hi))*10+nib(2,lo) %end %integerfn pg(%integer channel, %integer page) !Takes page specified as an integer channel plus !page number (we hope as a decimal number, 100<=n<=999) and turns it into !a 16-bit integer, top 4 bits channel, bottom 12 page number as BCD. %integer h,t,d !! write(page,3); write(channel,3) h = page//100 page = page - h*100 t = page//10 d = page - t*10 channel = channel & 16_0F !! write(channel,3); write(h,3); write(t,3); write(d,3); newline %result=((channel<<4+h)<<4+t)<<4+d %end %conststring (255) %array getfail(-1:4) = %c {-1}"Server <-> Teletext receiver timeout", {0} "OK", {1} "Request cancelled", {2} "Server died while transmitting on ether", {3} "Server failed to transmit page to ether", {4} "Software error" %routine move(%integer bytes, %bytename from, to) !Move BYTES bytes from FROM to TO. Pinched from IE. !If addr(FROM) < addr(TO) do the move from the top down to allow overlap %return %if Bytes = 0 %or From == To %if Addr (To) < Addr (From) %start *Subq.l #1, d0 f loop: *move.b (a0)+, (a1)+ *dbra d0, f loop %else *add.l d0, a0 *add.l d0, a1 *subq.l #1, d0 b loop: *move.b -(a0), -(a1) *dbra d0, b loop %finish %end %ownstring(40) spaces40 = " " %integerfn get subpage from server(%integer param, to, %integername status) %string (255) command %bytearray buffer(0:1279), coda(0:511) %integer rc,rc2,n,i %routine unpack teletext(%bytearrayname buffer, to(0:1279)) %integer row, p, mag,i %bytearray check(0:31) !Note: Rows 26, 28 and 29 are not transmitted. There may be up to 4 !row 27s. I put the first row 27 in row 27 and any others in rows !26 then 28 and 29. !Unused rows have MAG and ROW set to 0. p=0 %for i=0,1,31 %cycle; check(i)=0; %repeat %for i=0,1,23 %cycle ;!Max. of 24 42-byte rows in 1024 chars mag=buffer(p); row=buffer(p+1) %if mag#0 %start %if row=27 %start !Clumsy !does it in received order without dehamming the subrow no. row=26 %if check(27)#0 row=28 %if check(26)#0 row=29 %if check(28)#0 %finish move(40, buffer(p+2), to(row*40)) check(row)=1 %finish p=p+42 %repeat !Fill in empty rows - assumed to contain spaces %for row=1,1,31 %cycle %if check(row)=0 %start move(40, charno(spaces40, 1), to(row*40)) %finish %repeat to(5) = buffer(0) ;!Save the magazine in an unused header byte status = buffer(5)<<8+(buffer(6)&255) %end command = "B".itos(param,-1) rc=server handshake(command, 200, buffer, n) %if rc=0 %start ;!Success %if n=512 %start !Expect the 2nd frame fragment n= get ether (my port,array(addr(buffer(512))), 6) %if n=512 %start !Then the status message n=get ether(my port,coda,512) !Now unpack the frame unpack teletext(buffer, array(to)) %else !Server died between sending blocks 1 and 2. %result=2 %finish %else %result=3 %finish %else %if rc>0 %start !! rc2=server handshake("E",5,array(to),n) !Note possibility for confusion if the cancel crosses the pages !coming back. Sort this later. %finish %finish %result=rc %end %integerfn mod10(%integer no); %result = no - (no//10)*10; %end %integerfn mod100(%integer no); %result = no - (no//100)*100; %end %constinteger %c erase page = 16_08, {byte 4} newsflash = 16_10, {byte 4} subtitle = 16_20, {byte 4} suppress header = 16_01, {byte 5} update indicator = 16_02, {byte 5} out of sequence = 16_04, {byte 5} inhibit display = 16_08, {byte 5} serial magazine = 16_10 {byte 5} %string (15) %fn statusbits(%integer status) !Returns the frame status bits as a string %byte c4,c5 %string (15) s c4 = status>>8; c5 = status & 16_FF s="" s=s."e" %if c4 & erase page # 0 s=s."n" %if c4 & newsflash # 0 s=s."s" %if c4 & subtitle # 0 s=s."h" %if c5 & suppress header # 0 s=s."u" %if c5 & update indicator # 0 s=s."o" %if c5 & out of sequence # 0 s=s."i" %if c5 & inhibit display # 0 s=s."m" %if c5 & serial magazine # 0 s=s."?" %if c4 & (\(erase page ! newsflash ! subtitle)) # 0 %or %c c5 & (\(suppress header ! update indicator ! out of sequence ! %c inhibit display ! serial magazine)) # 0 s="[".s."]" %unless s="" %result=s %end %predicate alpha colour(%byte ch) %trueif 1<= ch&127 <= 7 %false %end %predicate graphics colour(%byte ch) %trueif 17 <= ch&127 <= 23 %false %end %predicate alpha control(%byte ch) %true %if ch&127=release graphics %false %end %predicate graphics control(%byte ch) %true %if ch&127=hold graphics %or %c ch&127=contiguous graphics %or %c ch&127=separated graphics %false %end %predicate graphics present %on 0 %start %false %finish plot(0,0) %true %end %routine print row (%byte row, %integer col, %bytearrayname page (0:31,0:MaxC)) %byte ch, background colour, last graphics char, mode, display colour %integer column, temp font %on 0 %start; %return; %finish %routine select font(%integer font no) current font = font no font(font store(current font)) %end %routine process control(%bytename fch) ! set alpha colour %byte ch ch=fch&127 %if alpha colour(ch) %start %if mode & double height mask # 0 %then select font(double text) %c %else select font(text) mode = mode & \graphics mode display colour = ch colour (ch) ch = ' ' last graphics char = ' ' %elseif graphics colour(ch) ! set graphics colour and font display colour = ch - 16 colour(display colour) %if mode & held mode # 0 %then ch = last graphics char %else ch=' ' %if mode & separated graphics mask # 0 %start ! select separated graphics %if mode & double height mask # 0 %start select font(double sep graphics) %else select font(sep graphics) %finish %else ! select contiguous graphics font %if mode & double height mask # 0 %start select font(double graphics) %else select font(graphics) %finish %finish mode = mode! graphics mode %elseif ch = contiguous graphics mode = mode & \separated graphics mask ! change graphics font type to contiguous %if mode & double height mask # 0 %start select font(double graphics) %else select font(graphics) %finish ch = last graphics char %elseif ch = separated graphics ! change graphics font type to contiguous mode = mode! separated graphics mask %if mode & double height mask # 0 %start select font(double sep graphics) %else select font(sep graphics) %finish ch = last graphics char %elseif ch = hold graphics ! font (graphics font) mode = mode! held mode ch = last graphics char %elseif ch = release graphics mode = mode & \held mode ch = last graphics char %elseif ch = new background background colour = display colour ch = last graphics char %elseif ch = black background background colour = black ch = last graphics char %elseif ch = double height select font(current font+3) %if current font <= 2 !this is either the double-graphics command or the masked-out characters !following it. %if fch=141 %then ch=141 %else ch=last graphics char mode = mode! double height mask %elseif ch = normal height select font(current font-3) %if current font >= 3 ch = last graphics char mode = mode & \double height mask %else ch = last graphics char %finish fch=ch %end %routine an show sym(%integer fc) %integer desc, descend, c c=fc&127 desc = (((current font<<8)+background colour)<<8+display colour)<<8+fc %if desc # virscreen(row,column) %start %unless c = 127 %and mode & graphics mode # 1 %start colour (background colour) !Do a big background for double-height fonts. %if dh(row)#0 %then descend=font h %else descend=0 fill(column*font w, 476-row*font h-descend, (column+1)*font w-1, 476-(row-1)*font h-1) colour(display colour) %finish %if current font<=2 %then descend=0 ;!small chars on a double-ht line text at(column*font w, 476-row*font h-descend) %and show symbol(c) %c %unless c = ' ' %or c=13 virscreen(row,column) = desc %finish %end %return %if graphics flag=0 select font(text) last graphics char = ' '; mode = default mode; display colour = white background colour = black colour (display colour) %for column = 0, 1, MaxC %cycle ch = page (row, column) %if ch & 16_20#0 %and mode&held mode#0 %then last graphics char=ch&127 %if ch&127 < 32 %then process control(ch) ;!Leaves ch= ' ' or last graphics char an show sym (ch) %repeat %end %routine print wy row (%byte row, %integer C column, %bytearrayname page(0:31,0:39)) %byte mode, last graphics char, display colour, background colour %integer column, c, current mode %constinteger normal=0, underline=8, dim=1, graphic=16 %byte ch,ttmode %routine change mode set shade(mode) current mode=mode %end vt at(row, 0) set shade(normal) %for column = 0, 1, MaxC %cycle ch = page(row,column) %if graphics colour(ch) %or graphics control(ch) %start ttmode=graphic %elseif alpha colour(ch) %or alpha control(ch) ttmode=normal %finish mode=normal %if ch<32 %start ch=32 %elseif ch<64 mode=intense %if ttmode=graphic %elseif ch<96 %elseif ch<128 mode=intense %if ttmode=graphic %elseif ch<160 ch=ch-64; mode=intense %elseif ch<192 ch=ch&127 mode=intense %if ttmode=graphic %elseif ch<224 ch=ch&127 %else ch=ch&127 mode=intense %if ttmode=graphic %finish %if column = C column %start ;!Flip mode over cursor %if mode=intense %then mode=normal %else mode=intense change mode %if mode=normal %then mode=intense %else mode=normal %else change mode {%if mode # current mode} %finish printsymbol(ch) %repeat %end %integerfn succR(%integer row) !Return the number of the next valid row. This looks after wraparound !and blocks access to the lower row of a double-height row %if row#MaxR %and dh(row)#0 %start row=row+1; row=0 %if row>MaxR %finish row=row+1; row=0 %if row>MaxR %result=row %end %integerfn predR(%integer row) !Return the number of the previous valid row. This looks after wraparound !and blocks access to the lower row of a double-height row row=row-1; row=MaxR %if row<0 %if row#0 %and dh(row-1)#0 %start row=row-1; row=MaxR %if row<0 %finish %result=row %end %routine show screen(%integer pg,C row, C column) %integer row, column, char pointer, col %bytearray page(0:31,0:MaxC) %constinteger hi=0, lo=1 %integerfn nib(%integer offset,hilo) %integer n n = byteinteger(pg+offset) %if hilo=hi %then n=n>>4 %result=n&15+'0' %end ;!of nib move(1280, byteinteger(pg), page(0,0)) page(0,0) = nib(5,lo) page(0,1) = nib(0,hi) page(0,2) = nib(0,lo) page(0,3) = nib(1,hi) page(0,4) = nib(1,lo) page(0,5) = nib(2,hi) page(0,6) = nib(2,lo) row=0 %cycle %if row=C row %then col = C column %else col = -1 print wy row (row,col, page); print row(row,col, page) row=SuccR(row) %repeatuntil row=0 %end ;!of show screen %routine spot dh(%integer base) %integer row, column,p %for row=0,1,MaxR %cycle dh(row)=0 %repeat p=base %for row=0,1,MaxR %cycle %for column=0,1,MaxC %cycle dh(row)=dh(row)+1 %if byteinteger(p)&127=double height p=p+1 %repeat %repeat %end %integerfn get page from server(%integer page, base, %integername subpages) %integer rc, full pageno, f, firstf, maxsub, i, latestf, to, status firstf=-1; f=0; subpages=-1; maxsub=-1 !Once the subpages have wrapped round, we know we have a complete page !and how big it is. subpages=0 %cycle to = base + f * 1280 rc=get subpage from server(page, to, status) %result=rc %if rc#0 full pageno = txstoi(to) spot dh(to) show screen(to,-1,-1) latestf=f; f = mod100(full pageno) ;!the subpage number %if firstf<0 %start;!start point in subpage cycle firstf=f !Page is in subpage-0 slot. Copy the page to the correct place move(1280,byteinteger(to), byteinteger(base+(f-1)*1280)) %if f>1 %finish %if f=0 %start; !Only subpage flag comment(" Page ".itos(full pageno,-1)." ".status bits(status)) subpages=1 %result=0 %elseif f=latestf ;!subpages are looping flag comment("Subpage ".itos(full pageno,-1)." looping") subpages=1 %result=0 %else flag comment("Subpage ".itos(full pageno,-1)." ".status bits(status)." arrived") %finish %if f=0; %end flag comment("Use up and down arrows to scan page.".snl. %c "Press to exit") minbase=lo*1280; maxbase=hi*1280 offset=minbase %cycle; %repeatuntil testsymbol<0 %cycle spot dh(base+offset) show screen(base+offset,-1,-1) %cycle r %if c=27 %start r %if c=91 %start r %if c=65 %start ;!Up %if offset>minbase %then offset=offset-1280 %else offset=maxbase %elseif c=66 ;!Down %if offset=0 rc=get page from server(page, pagestore, subpages) %if rc=0 %and subpages#0 %start !! %if subpages>1 %start !! show prompt("browse?") !! %cycle !! f=testsymbol !! f='N' %if f=13 %or f=10 %or f='n' !! f='Y' %if f='y' !! %repeatuntil f='Y' %or f='N' !! %if f='Y' %start !! browse(pagestore, 0, subpages-1) !! %finish %else flag error("Page request failed - ".getfail(rc).snl. %c "Press to continue") %cycle; %repeatuntil testsymbol=' ' %finish %repeat %end %owninteger subpages=0 %routine design %integer font w, font h, m x, m y, char x, char y, old m x, old m y %constinteger cursor plane = 8, rest = 7, TRUE = 1, FALSE = 0 %routine printline(%string (255) s) printstring(s); newline %end ;!of printline in design %routine setup screens set frame(0,24,0,80) clear frame %if graphics flag = true %start clear Offset (0,0) enable(rest) %finish set terminal mode(no page) %end ;!of setup screens in design ! draw cursor: draw a box round the character box containing (x,y) ! i.e. snap the cursor onto the character grid %routine draw cursor(%integer row,column,h) %integer x,y %on 0 %start; %return; %finish x = column*font w y = 476-row*font h - (h-1)*font h enable(cursor plane) colour(32767) hline (x,x+font w,y) hline (x,x+font w,y+font h*h) vline (x,y,y+font h*h) vline (x+font w,y,y+font h*h) enable(rest) %end ;!of - in design ! undraw cursor: erases the cursor from the screen %routine undraw cursor(%integer row,column,h) %integer x,y %on 0 %start; %return; %finish x = column*font w y = 476-row*font h - (h-1)*font h enable(cursor plane) colour(0) hline(x,x+font w,y) hline(x,x+font w,y+font h*h) vline(x,y,y+font h*h) vline(x+font w,y,y+font h*h) enable(rest) %end ;!of - in design %integerfn get m position ! ! Repeats a loop polling the m position until a button is pressed ! %integer temp buttons, x off, y off, t set frame(15,5,0,40) clear frame print string("PLEASE SELECT MENU OPTION :-") %cycle x off = rel mouse x y off = rel mouse y m x = m x + x off m y = m y + y off %if mx > 39 * fontw %then mx = 39*fontw %elseif mx < 0 %then mx = 0 %if my > 23 * fonth %then my = 23*fonth %elseif my < 0 %then my = 0 %if m x # old m x %or m y#old m y %start undraw cursor(old m x, old m y,0) old m x = m x; old m y=m y draw cursor(old m x, old m y,0) char x = m x // font w char y = m y // font h !write(23-char y,5);write(char x,5);newline %finish temp buttons = test symbol - '0' %repeatuntil 1<=temp buttons <= 8 newline %return temp buttons %end ;!of - in design ! setup designer: intialise the variables and framestore for use by the ! designer %routine setup designer setup screens m x = 320 m y = 256 old m x = 0 ; old m y = 0 font w = max font width font h = font height %end ;!of - in design %routine load file(%string (255) name,%bytearrayname p(0:31,0:MaxC)) %label abort %integer i,j,t %on 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 %start flag error("Sorry cannot load ".name." because ".event_message) ->abort %finish open input(1,name) select input(1) %for i=0,1,MaxR %cycle %for j=0,1,MaxC %cycle read symbol(t) p(i,j) = t {NEEDED FOR VTLIB %repeat %repeat spot dh(addr(p(0,0))) show screen(addr(p(0,0)), 0,0) abort: close input select input(0) %end ;!of - in design %routine save file(%string (255) name) %label abort %integer i,j %on 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 %start flag error("Sorry cannot do that because ".event_message) -> abort %finish open output(1,name) select output(1) %for i=0,1,MaxR %cycle %for j=0,1,MaxC %cycle printsymbol(page(i,j)) %repeat %repeat abort: close output select output(0) %end ;!of - in design !!!%integerfn pg(%integer channel, %integer page) !!! !Takes page specified as an integer channel plus !!! !page number (we hope as a decimal number, 100<=n<=999) and turns it into !!! !a 16-bit integer, top 4 bits channel, bottom 12 page number as BCD. !!! !!! %result=(page&16_FFF) ! (channel&16_0F)<<12 !!!%end ;!of - in design %routine save to db(%integer location, %string(255) comments) %integer page id page id = pg(5, location) !Forget comments write cached page(page id, addr(page(0,0)), 1) %end ;!of - in design %routine load from db(%integer channel, location) %integer page id, subpages page id = pg(channel, location) read cached page(page id, addr(page(0,0)), subpages) %if subpages#0 %start spot dh(addr(page(0,0))) show screen(addr(page(0,0)),-1,-1) %else flag error("Page not present") %finish %end ;!of - in design %routine do design %constinteger norm=0 %integer i,j,mode,control,channel,row,column,c,finished %string (255) line %integerfn C mode(%integer row, col) %constinteger normal=0, underline=8, dim=1 %byte ch, mode ch = page(row, col) %if row=0 %start mode=intense %elseif ch<32 mode=normal %elseif 32<=ch<=127 mode = normal %elseif 129<=ch<=135 mode=normal %elseif 156<=ch<=157 ;!New background mode=normal %elseif 128<=ch<=159 mode=intense %else mode=intense %finish %result = mode %end ;!of - in do design in design %routine zap cursor %integer h set shade(C mode(row, column)) vt at(row,column); printsymbol(page(row,column)) %if dh(row)=0 %then h=1 %else h=2 undraw cursor(row, column, h) %end ;!of - in do design in design %routine paint cursor %integer mode,h %constinteger normal=0, underline=8, dim=1 mode = C mode(row, column) vt at(row, column) %if mode = normal %then set shade(intense) %else set shade(normal) print symbol(page(row,column)) %if dh(row)=0 %then h=1 %else h=2 draw cursor(row, column, h) %end ;!of - in do design in design %routine C right zap cursor column = column + 1 %if column > MaxC %start { Wrapround column = 0 ; row = succR(row) %finish paint cursor %end ;!of - in do design in design %routine C down zap cursor row = succR(row) paint cursor %end ;!of - in do design in design %routine C return zap cursor row=succR(row); column=0 paint cursor %end %routine C up zap cursor row = predR(row) paint cursor %end ;!of - in do design in design %routine C left zap cursor column = column - 1 %if column < 0 %start { Wrapround column = MaxC ; row = predR(row) %finish paint cursor %end ;!of - in do design in design %routine zap line(%integer row) %integer column %for column=0,1,MaxC %cycle; page(row,column) = ' '; %repeat dh(row)=0 %end %routine C home zap cursor row=0; column=0 paint cursor %end ;!of - in do design in design %routine get(%integername c) %cycle; c=testsymbol; %repeatuntil c>=0 %end %routine add(%byte c) %constinteger normal=0 zap cursor %if page(row, column)&127 = double height %start %if c&127#double height %then dh(row) = dh(row) - 1 %else %if c&127=double height %then dh(row) = dh(row) + 1 %finish page(row, column) = c ! paint cursor {no point - C Right will wipe it again} vt at(row, column); %if c<=127 %then printsymbol(c) %elsestart set shade(intense); printsymbol(c&127+'A'); set shade(normal) %finish !t flag comment("add ".itos(page(row,column),-1)." ".itos(row,-1)." ".itos(column,-1)) C right %end ;!of add in do design in design %constintegerarray f(1:12) = 0,31,59,90,120,151,181,212,243,273,304,334 %conststring (3) %array dy(0:6) = "Mon", "Tue", "Wed","Thu", "Fri", "Sat", "Sun" %string (9) %fn weekday(%string (*) %name date) !Returns the day of week of the supplied date. Works for all dates in the !format dd/mm/yy, yy assumed to be between 1900 and 1999. !White space on front of date is ignored and so is garbage after the date bit. %integer day, month, year, i i = 1 i = i + 1 %while charno(date, i) < '0' ;!Skip past leading junk !Split date up into day, month, year day = stoi(substring(date, i, i+1)) month = stoi(substring(date, i+3, i+4)) year = stoi(substring(date, i+6, i+7)) day = f(month) + day ;!Past months this year + days this month day = day + 1 %if year & 3 = 0 %and year # 0 %and month > 2 ;!Leap year correction !Complete past years + correction for day-of-week of 1/1/00 day = day + year * 365 + 6 day = day + (year-1)>>2 %if year # 0 ;!past leap years %result = dy(day - (day//7)*7) %end %routine form header(%bytearrayname pg(0:31, 0:MaxC), %integer pageno) %integer t %string (255) d %routine p(%byte val); pg(0,t) = val; t=t+1; %end %routine ps(%string (63) s) %integer i %for i=1,1,length(s) %cycle; p(charno(s,i)); %repeat %end t=0 d = date p(mod100(pageno)//10<<4+mod10(pageno)); p(0); p(0); p(0); p(0); p(pageno//100) ps(" EU.CSD ".itos(pageno,3)." ".weekday(d)." ".d." ".time) %end ! Do Design - Main code %for row=0, 1, MaxR %cycle; zap line(row); %repeat row=0; column=0 finished = false form header(page, 500) show screen(addr(page(0,0)),0,0) C home %cycle get(c) %if c = escape %start get(c) %if c=cursors %start get(c) %if c = uparrow %start C up %elseif c = downarrow C down %elseif c = leftarrow C left %elseif c = rightarrow C right %elseif c = home C home %finish %elseif c=keypad get(c) %if pad1<=c<=pad7 %start add(c-pad0+128) mode=norm print wy row(row, column, page); print row(row,column, page) flag comment2(itos(c,3).itos(page(row,column), 3)) %elseif c=pad8 add(128+normal height) print wy row (row,column, page); print row(row,column, page) %elseif c=pad9 %and row#MaxR %and dh(row+1)=0 zap line(row+1) add(128+double height) print wy row (row,column, page); print row(row,column, page) %elseif c=pad0 get(c) %if c=escape %start get(c) %if c=keypad %start get(c) %if pad1<=c<=pad7 %start add(c-pad0+144) %elseif c=pad8 add(128+black background) %elseif c=pad9 add(128+new background) %finish print wy row(row, column, page); print row(row, column, page) %finish %finish %elseif c=pf1 show prompt("LOAD file:") read line(line) %if line#"" %then load file(line,page) %elseif c=pf2 show prompt("SAVE file:") read line(line) save file(line) %elseif c=pf3 show prompt("LOAD channel:") read(channel) show prompt("LOAD page id:") read(control) load from db(channel, control) %elseif c=pf4 show prompt("SAVE id:") read(control) show prompt("Comment line:") read line(line) line = current user." <-> ".line save to db(control, line) %elseif c=padcomma zap line(row) show screen(addr(page(0,0)),row,column) %elseif c=padminus %for i=0,1,MaxR %cycle zap line(i) %repeat show screen(addr(page(0,0)),row,column) %elseif c=enter finished = true %finish %finish %elseif c=13 C return %elseif c=delete C left add(' ') C left print wy row(row, column, page); print row(row,column,page) %else add(c) print wy row(row, column, page); print row(row,column,page) %finish %repeatuntil finished = true clear frame %end ;!of do design in design %routine show menu print at line(0, " 1:alpha red 2:alpha green") print at line(1, " 3:alpha yellow 4:alpha blue") print at line(2, " 5:alpha magenta 6:alpha cyan") ! 1-7 alpha colours: red,green,yellow,blue,magenta,cyan,white ! 8: flash, 9: steady, 10,11: unused ! 12: normal height, 13: double height ! 14,15,16: unused ! 17-23 graphic colours: red,green,yellow,blue,magenta,cyan,white ! 24: conceal ! 25: contig graphics, 26: sep graphics ! 27: unused ! 28:black background 29:new background ! 30:hold graphics 31:release graphics print at line(3, " 7:alpha white 8:normal height") print at line(4, " 9:double height 01:graphic red") print at line(5, "02:graphic green 03:graphic yellow") print at line(6, "04:graphic blue 05:graphic magenta") print at line(7, "06:graphic cyan 07:graphic white") print at line(8, "08:black background 09:new background") print at line(9, "25:contig graphics 26:sep graphic") print at line(10, "30:hold graphics 31:release graphics") print at line(11, "") print at line(12, "CONTROL CODES") print at line(13, "pf2: Save page to file") print at line(14, "pf1: Load page from file") print at line(15, "pf4: Save page to db") print at line(16, "pf3: Load page from db") print at line(17, " - : Clear page") print at line(18, " , : Clear line") print at line(19, "enter: quit") print at line(20, "") print at line(21, "") print at line(22, "") print at line(23, "") %end ;!of - in design !%integer i set video mode(specialpad) { To initialise the TERMLIB stuff setup designer show menu !!%cycle !i=testsymbol; %if i>=0 %start; write(i, 3); newline; %finish; %repeat do design %end ;!of design %externalroutine an clear %integer i,j %for i=0,1,31 %cycle; %for j=0,1,39 %cycle; virscreen(i,j)=0; %repeat; %repeat clear %end %routine act on (%integer comm, param) %switch entry('B':'H') %bytearray buffer(0:1279) %half page %integer rc, page id -> entry(comm) entry('B'): !Read a page from cache if available then broadcast if not page id = pg(channel, param) open cache(database file) read cached page(page id, pagestore, subpages) close cache %if channel = 5 %start flag error("Page not available") %if subpages=0 %else %if subpages=0 %start flag error("Page not available") %elseif subpages=1 show screen(pagestore,-1,-1) %else browse(pagestore, 0, subpages-1) %finish %finish %return entry('C'): !Change channel channel = param rc=server handshake(tostring(command).itos(channel,-1), 60, buffer, n) %return entry('D'): !Quit %if cache only # true %start rc=server handshake(tostring(command), 1, buffer, n) ether close(my port) %finish clear frame %return entry('E'): !Force a page request from server page id = pg(channel, param) open cache(database file) read cached page(page id, pagestore, subpages) close cache flag comment("Page from cache") %and showscreen(pagestore,-1,-1) %if subpages#0 %if channel = 5 %start flag error("Cannot force a download on channel 5") %else %if cache only = true %start flag error("Trying to reconnect to server") %if start talking %start flag comment("OK.") cache only = false %finish %finish %if cache only = false %start open cache(database file) rc=get page from server(param, pagestore, subpages) %if rc=0 %start %if subpages>1 %then browse(pagestore, 0, subpages-1) page id = pg(channel, param) flag comment 2("Caching page".snl."") write cached page(page id, pagestore, subpages) %else flag error("Page request failed - ".getfail(rc).snl. %c "Press to continue") %cycle; %repeatuntil testsymbol=' ' %finish close cache %else flag error("Cannot force page - server not responding") %finish %finish %return entry('F'): show prompt("SAVE file name:"); %cycle vt at(prompt row+1,menu col) read line(filename) %repeatuntil filename#"" open output(1,filename) select output(1) %for i=0,1,32*40*subpages-1 %cycle print symbol(byteinteger(pagestore+i)) %repeat close output select output(0) %return entry('G'): open cache(database file) design close cache an clear %return entry('H'): %if channel = 5 %start flag error("Cannot carousel on channel 5") %else open cache(database file) carousel(param) close cache %finish %end %routine get command(%integername comm, param) !Show menu, get and validate command. %ownbytearray table('1':'7') = 'B','E','C','F','H','G','D' %integer c %on 10 %start !Bad integer typed in. flag error("Bad integer supplied".snl.%c "Press space to continue") %cycle; %repeatuntil testsymbol=' ' %finish clear frame %if graphics flag#0 set shade(reverse+intense+blink+underline) title line("APMTEL on channel ".itos(channel,-1).":") set shade(0) line(1) print at line(menu row, %c "1:Get page".snl. %c "2:Force get".snl. %c "3:Channel".snl. %c "4:Save to file".snl. %c "5:Carousel page".snl. %c "6:Design page".snl. %c "7:QUIT".snl) !The explicitly written rows will put a | in rows 0-10. %if graphics flag=0 %start %for c=11,1,23 %cycle; vt at(c, divider col); printsymbol('|'); %repeat %finish flag error("".snl.""); flag comment("".snl."") show prompt("?:") %cycle c = test symbol %repeatuntil '1' <= c <= '7' comm = table(c); param=0 %if comm='B' %or comm='H' %or comm='E' %start ! 'B': Get page, 'E': Force get from broadcast, 'H': Carousel show prompt("Page:") %cycle read(param) %exit %if 100<=param<=999 flag error("Valid pages 100-999 only") vt at(prompt row+1,menu col) %repeat %elseif comm='C' !Select channel show prompt("Channel:") %cycle read(param) %exit %if 1<=param<=5 flag error("Valid channels 1 (BBC1), 2(BBC2), 3(STV), 4(Channel 4), 5(EUCSD) only") vt at(prompt row+1, menu col) %repeatuntil 1<=param<=5 %elseif comm='D' !Quit %finish !t!flag comment(itos(c, 3)." ".tostring(comm)) %end %predicate flagset(%integer c) %integer i %false %if cli param="" %for i=1,1,length(cli param) %cycle %true %if charno(cli param,i) & 16_5F = c&16_5F %repeat %false %end %externalroutine load fonts readfont("apmtel:TFONT0.BFT", font store (text)) readfont("apmtel:TFONT1.BFT", font store (graphics)) readfont("apmtel:TFONT2.BFT", font store (sep graphics)) readfont("apmtel:TFONT0DH.BFT", font store (double text)) readfont("apmtel:TFONT1DH.BFT", font store (double graphics)) readfont("apmtel:TFONT2DH.BFT", font store (double sep graphics)) font(font store(text)) font w = max font width font h = font height %end %if flagset('v') %then graphics flag=0 %elsestart %if graphics present %then graphics flag=1 %else graphics flag=0 %finish pagestore = heapget(100*1280) set video mode(specialpad) clear frame channel = 1 %if flagset('l') %then cache only = true %elsestart %if start talking %then cache only = false %else cache only = true %finish %if graphics flag#0 %start an clear flag comment("Loading fonts ") load fonts { Load the teletext fonts up %finish %cycle get command(command, param) { Get a menu choice ..... act on(command, param) %repeatuntil command='D' %if cache only # true %then etherclose (myport) heapput(pagestore) %endofprogram