From: hansk@aie.nl (Hans Kinwel)
Subject: Re: gevraagd: unix viditel programma
Organization: AI Engineering BV, Amsterdam, Netherlands
Distribution: nlnet
Date: Tue, 5 Jan 1993 02:30:51 GMT

In article <4327@wzv.win.tue.nl> guido@gvr.win.tue.nl (Guido van Rooij) writes:
>...
>wie heeft voor mij de sources van een viditel programma (om te girotellen
>vanaf een unix machine).
>Verder ben ik op zoek naar een specifictie van het protocol.

Ik had de volgende posting gesaved.  Dit moet een end in de richting
komen denk ik zo.  Voor meer informatie verwijs ik je natuurlijk naar 
Jan Christiaan.

Groeten, Hans 

======================================================================
Newsgroups: nlnet.misc
From: jc@cs.kun.nl (Jan Christiaan van Winkel)
Subject: Re: videotext protocol: eindelijk
Date: Wed, 12 Feb 1992 21:09:29 GMT

In <1992Feb12.101653.20762@sci.kun.nl> jc@cs.kun.nl (Jan Christiaan van Winkel) writes:

>Via via via via heb ik eindelijk (het grootste deel van) de videotext
>protocol beschrijving te pakken weten te krijgen. Ik heb e.e.a. in een
>rudimentair programma omgezet (waarmee ik dus vanaf mijn UNIX-doosje
>kan girotellen, telefoonnummers opvragen etc etc.)

>Is er belangstelling voor gegevens over dit protocol? Ik heb zelf tot
>twee maal toe gevraagd wie wat wist, en ik kreeg alleen maar me-too
>replies terug. Als er voldoende belangstelling is zal ik 1) een korte
>beschrijving maken enop het net zetten en 2) het programma wat
>oppoetsen en posten.

Nou, hier is dan de beschrijving. Het programma is nog ietwat pre-alpha
om het zo maar te zeggen, ik post hier alleen de interpretatie van wat
er binnenkomt van de andere kant.

Veel plezier/succes.
JC

De beschrijving:
======================
Korte beschrijving van het videotextprotocol.

1) het display bevat 24 regels van 40 characters. linksboven is (1,1).
Iedere characterpositie bevat 1) een te displayen object en 2) een aantal
attributen. Het te displayen object kan zowel grafisch zijn, als een
'gewoon' ascii character. De attributen zijn: voorgrondkleur,
achtergrondkleur, knipperen wel/niet, 'box' wel/niet (?) normale
hoogte/dubbele hoogte, verborgen display wel/niet (a la teletext),
grafische blokjes aan elkaar vast of los.

2) De default attributen van het display zijn: alfanumeriek (dus niet
grafisch), achtergrond zwart, voorgrond wit, niet knipperend, geen box,
normale hoogte, grafische blokjes aan elkaar vast, niet verborgen.

3) de default scherminhoud is een spatie (zoals te verwachten), cursor op
(1,1), cursor uit.

4) Op een paar speciale symbolen na, zijn all characters in de standaard ascii
set >=0x20 <=0x7e de te verwachten symbolen. 
Behalve: 
0x23 (normaliter #), het pondteken
0x5b (normaliter [): pijltje naar links, 
0x5d (]) pijltje naar rechts,
0x5e (^) pijltje omhoog, 
0x5f (_) het hekje (#), 
0x7b ({) het symbool 1/2,
0x7c (|) twee vertikale streepjes omhoog (sort of ||), 
0x7d (}) het symbool 1/4, 
0x7e (~) het gedeeld door teken (a la lagere school: : met - erdoor),
0x7f: een volledig positie vullend symbool.

5) De volgende control characters zijn gedefinieerd: 
0x08: zet de cursor op vorige positie van het scherm. Als deze al op kolom 
1 stond, ga naar kolom 40 van de vorige regel. Als je op regel 1 stond, 
ga naar regel 24. 
0x09: cursor een positie naar rechts. als je op positie 40 stond, ga naar 
de volgende regel, als je op regel 24 stond, ga naar regel 1. 
0x0a: ga naar de volgende regel. stond je op regel 24, ga naar regel 1. 
0x0b: ga een regel omhoog. Stond je op regel 1, ga naar regel 24. 
0x0c: zet het hele scherm op de default attributen (en dus: wis het scherm). 
0x0d: zet de cursor op kolom 1. 
0x11: zet de cursor aan. 
0x14: zet de cursor uit.
0x1e: zet de cursor op (1,1) (cursor home).

6) het is mogelijk dat je een escape sequence binnekrijgt: <esc><code>.
<esc> is hierbij 0x1b. <code> is uit de range 0x40 tot en met 0x5f.
Steeds geldt bij het binnenkrijgen van een escape sequence dat je op het
scherm *een* positie inneemt. (wat dat betreft lijkt e.e.a. dus op het
magic cookie van de televideo 925 terminals). De ingenomen positie is
een spatie, tenzij je in de mode 'hold grafics' (zie verderop) was, dan
wordt het meest recente grafics character genomen. De codes zijn:
<esc>0x41: zet voor de rest van de regel vanaf de huidige positie de 
attributen op alfanumeriek, voorgrondkleur rood
<esc>0x42: idem groen
<esc>0x43: idem geel
<esc>0x44: idem blauw
<esc>0x45: idem magenta
<esc>0x46: idem cyaan
<esc>0x47: idem wit (default)
<esc>0x48: zet voor de rest van de regel vanaf de huidige positie 
de attributen op knipperend
<esc>0x49: zet voor de rest van de regel vanaf de huidige positie 
de attributen op niet knipperend (default)
<esc>0x4a: 'end box' ?
<esc>0x4b: 'start box' ?
<esc>0x4c: zet voor de rest van de regel vanaf de huidige positie 
de attributen op normale hoogte
<esc>0x4d: zet voor de rest van de regel vanaf de huidige positie 
de attributen op dubbele hoogte
<esc>0x51: zet voor de rest van de regel vanaf de huidige positie 
de attributen op grafisch, voorgrondkleur rood
<esc>0x52: idem groen
<esc>0x53: idem geel
<esc>0x54: idem blauw
<esc>0x55: idem magenta
<esc>0x56: idem cyaan
<esc>0x57: idem wit (default)
<esc>0x58: zet voor de rest van de regel vanaf de huidige positie 
de attributen op verborgen (tevoorschijn te toveren met een 'reveal' 
toets op het toetsenbord van zo'n videotext terminal)
<esc>0x59: zet voor de rest van de regel vanaf de huidige positie 
de attributen op grafisch aaneengesloten (default)
<esc>0x5a: zet voor de rest van de regel vanaf de huidige positie 
de attributen op grafisch niet aaneengesloten
<esc>0x5c: zet voor de rest van de regel vanaf de huidige positie 
de attributen op zwarte achtergrond (default)
<esc>0x5d: zet voor de rest van de regel vanaf de huidige positie 
het achtergrondattribuut op het voorgrondattribuut van het vorige 
character (ingewikkelde zaak hoor...:-)
<esc>0x5e: zet hold graphics aan: <esc><code> neemt geen spatie meer in
maar het laatst gebruikte grafische symbool.
<esc>0x5f: zet hold graphics aan. <esc><code> neemt weer een spatie in
op het scherm.

7) Grafics. Als een character weggeschreven wordt op een positie waarvan
het graphics attribuut aan staat, moet niet een gewoon character
weggeschreven worden, maar wat anders:
Ieder character wordt opgedeeld in een blokje met 6 pixels. het pixel
linksboven heeft waarde 1, rechtsboven waarde 2, midden links waarde 4,
midden rechts waarde 8, linksonder waarde 16 en rechtsonder 32. Dus:
het blokje
*.
.*
**  heeft waarde 0x39, ofwel 57. Maar we zijn er nog niet: De blokjes
met waarde 0x00 tot en met 0x1f worden gecodeerd in ascii met de waarden
0x20 tot en met 0x3f (spatie t.e.m. '?'), en de blokjes met waarde 0x20
tot en met 0x3f worden gecodeerd met de waarden 0x60 tot en met 0x7f (de
` tot en met de del). De characters met waarde 0x40 tot en met 0x5f
worden in de grafische mode net zo afgedrukt als in aplfanumerieke
mode.
De grafische blokjes kunnen netjes op elkaar aansluiten (grafisch
connected, default) en met een piepdun lijntje achtergrondkleur ertussen
(grafisch gescheiden).


======================
het programma. Leest van standard input. Is (nog) specifiek voor een
altos 2 terminal geschreven. met 1) de beschrijving en 2) het programma
moet je een heel eind kunnen komen denk ik zo.


#include <stdio.h>

int mode=0;
int col=1;
int row=1;
int charset=0;
int flashing=0;
int cursoron=1;

unsigned char lastgraphic=0x20;
int holdgraphic=0;

typedef enum { chr, fgcolor, bgcolor, flash, dblhgt,
  conceal, grcon, box, graphic
} attrib;

char init[]={ ' ', 7, 0, 0, 0, 0, 1, 0, 0 };

char screen[25][41][sizeof(init)];

void  curpos(), curright(), charcopy(), error(), graphchar(),
      nul(), curleft(), curdown(), curup(), cr(), curon(), 
      curoff(), curhome(), toc1(), cls(), setelem();

void setmode(ch)
unsigned char ch;
{
  if      (ch>=0x41 && ch<=0x47) {
    setelem(fgcolor, ch & 0x07); setelem(graphic,0);
  }
  else if (ch==0x48 || ch==0x49) setelem(flash, !(ch&1));
  else if (ch==0x4a || ch==0x4b) setelem(box, ch&1);
  else if (ch==0x4c || ch==0x4d) setelem(dblhgt, ch&1);
  else if (ch==0x4e || ch==0x4f) error(ch);

  else if (ch>=0x51 && ch<=0x57) {
    setelem(fgcolor, ch & 0x07);setelem(graphic,1);
  }
  else if (ch==0x58            ) setelem(conceal, 1);
  else if (ch==0x59 || ch==0x5a) setelem(grcon, ch&1);
  else if (ch==0x5b            ) error(ch);
  else if (ch==0x5c            ) setelem(bgcolor, 0);
  else if (ch==0x5d            ) setelem(bgcolor, curbgcolor());
  else if (ch==0x5e            ) holdgraphic=1;
  else   /*ch==0x5f            */holdgraphic=0;

  if (holdgraphic) graphchar(lastgraphic);
  else charcopy(' ');
  mode=0;
}

void curpos(r,c) 
int r,c;
{
  printf("\033[%d;%dH",r,c);
}

void curright(ch) {
  col++;
  if (col>40) {
    col=1;
    curdown(ch);
  } else if (ch) curpos(row, col);
}

void charcopy(ch) {

  screen[row][col][chr]=ch;

  if (screen[row][col][graphic] &&
      ((ch >= 0x20 && ch <=0x3f) || (ch >=0x60 && ch <= 0x7f))) {
    graphchar(ch);
    return;
  }
  
  if (ch!=' ' && charset!=0) {
    printf("\033(B");
    charset=0;
  }

  if (screen[row][col][flash]!=flashing) {
    printf("\033[%cm", flashing ? '0' : '5');
    flashing=!flashing;
  }
  switch (ch) {
    case 0x23: printf("\033(1%c", 0x3d) ; charset=1; break; /* pound sign */
    case 0x5b: putchar('<'); ; break; /* <- sign */
    case 0x5d: putchar('>'); ; break; /* -> sign */
    case 0x5e: putchar('^'); ; break; /* arrow-up */
    case 0x5f: putchar('#'); break;
    case 0x7b: printf("\033(1%c", 0x4c) ; charset=1; break; /* 1/2 sign */
    case 0x7c: printf("\033(0%c", 0x3a) ; charset=1; break; /* || sign */
    case 0x7d: printf("\033(1%c", 0x4d) ; charset=1; break; /* 1/4 sign */
    case 0x7e: printf("\033(1%c", 0x67) ; charset=1; break; /* divide sign */
    case 0x7f: printf("\033(1%c", 0x6f) ; charset=1; break; /* filled char */
    default: putchar(ch); break;
  }
  curright(0);
}

void setelem(attr, valu) 
int attr, valu;
{
  int i;
  for (i=col; i<=40; i++) screen[row][i][attr]=valu;
}

int curbgcolor() {
  return screen[row][col-1 > 0 ? col-1 : 1][bgcolor];
}

void graphchar(ch) 
unsigned char ch;
{
  static char xlate[64][2] = {
/*   0/8    1/9    2/a    3/b    4/c    5/d    6/e    7/f  */
    2, 33, 4, 49, 2, 45, 4, 61, 2, 65, 4, 81, 2, 77, 4, 93,  /* 20 */
    2, 35, 4, 51, 2, 47, 4, 63, 2, 67, 4, 83, 2, 79, 4, 95,  /* 28 */
    2, 49, 4, 65, 2, 61, 4, 77, 2, 81, 4, 97, 2, 93, 4,109,  /* 30 */
    2, 51, 4, 67, 2, 63, 4, 79, 2, 83, 4, 99, 2, 95, 4,111,  /* 38 */
    2, 34, 4, 50, 2, 46, 4, 62, 2, 66, 4, 82, 2, 78, 4, 94,  /* 60 */
    2, 36, 4, 52, 2, 48, 4, 64, 2, 68, 4, 84, 2, 80, 4, 96,  /* 68 */
    2, 50, 4, 66, 2, 62, 4, 78, 2, 82, 4, 98, 2, 94, 4,110,  /* 70 */
    2, 52, 4, 68, 2, 64, 4, 80, 2, 84, 4,100, 2, 96, 4,112,  /* 78 */
  };

  lastgraphic=ch; 

  ch-=0x20;
  if (ch>=0x20) ch-=0x20;
  if (charset!=xlate[ch][0]) {
    charset=xlate[ch][0];
    printf("\033(%d", charset);
  }
  putchar(xlate[ch][1]);

  curright(0);
}


void curleft(ch) {
  col--;
  if (col==0) {
    col=40;
    row--;
  }
  curpos(row, col);
}

void curdown(ch) {
  row++;
  if (row==25) row=1;
  if (ch) curpos(row, col);
}

void curup(ch) {
  row--;
  if (row==0) row=24;
  curpos(row, col);
}

void nul(ch) { }
void cr(ch) { if (col==1) return; col=1; curpos(row,col); }
void curon(ch) { if (cursoron) return; printf("\033[>5l"); cursoron=1;}
void curoff(ch) { if (!cursoron) return; printf("\033[>5h"); cursoron=0;}
void curhome(ch) { if (row==1 && col==1) return; row=col=1; curpos(row,col); }
void toc1(ch) { mode=1; }

void error(ch) { 
  
  /* debugging code */
  if (charset) { printf("\033(B"); charset=0; }
  printf("\0337\033[25;1H");
  if (mode) printf("\033[10@<esc><%02x>|", ch);
  else printf("\033[5@<%02x>|",ch);

  printf("\0338",ch);

  /* just beep */
  putchar('\007');   /* my name is Bond, James Bond */
  mode=0;
}


void cls(ch) {
  int i,j,k;

  cursoron=1;
  curoff(0);
  printf("\033[2J\033[H");

  for (i=1; i<=24; i++) {
    for (j=1; j<=40; j++) {
      for (k=0; k<sizeof(init); k++) {
        screen[i][j][k]=init[k];
      }
    }
    printf("\033#6");
    if (i!=24) putchar('\n');
  }
  row=24;
  curhome(0);
  if (ch==0) curon(0);
  holdgraphic=0;

}

void (*(funcarray[128]))() = {
  nul,          /* 0x00 nul */
  error,        /* 0x01 nul, soh */
  error,        /* 0x02 nul, stx */
  error,        /* 0x03 nul, etx */
  error,        /* 0x04 nul, eot */
  error,        /* 0x05 nul, enq */
  error,        /* 0x06 nul, ack */
  charcopy,     /* 0x07 bell */
  curleft,      /* 0x08 cursor left */
  curright,     /* 0x09 cursor right */
  curdown,      /* 0x0a cursor down */
  curup,        /* 0x0b curup */
  cls,          /* 0x0c clear screen */
  cr,           /* 0x0d carriage return */
  nul,          /* 0x0e nul, so */
  nul,          /* 0x0f nul, si */

  error,        /* 0x10 nul, dle */
  curon,        /* 0x11 cursor on */
  error,        /* 0x12 nul, dc2 */
  error,        /* 0x13 nul, dc3 */
  curoff,       /* 0x14 cursor off */
  error,        /* 0x15 nul, nak */
  error,        /* 0x16 nul, syn */
  error,        /* 0x17 nul, etb */
  error,        /* 0x18 nul, can */
  nul,          /* 0x19 nul, em */
  error,        /* 0x1a nul, sub */
  toc1,         /* 0x1b toc1 */
  error,        /* 0x1c nul, ss2 */
  nul,          /* 0x1d nul, ss3 */
  curhome,      /* 0x1e cursor home */
  error,        /* 0x1f nul, us */
};

main()
{
  unsigned char ch;
  setbuf(stdout,  NULL);

  cls(0);
  printf("\033[>1h");

  while (read(0, &ch, 1) > 0) {
    
    if (mode) {
      if (ch > 0x40 && ch<=0x5f) setmode(ch);
      else { error(ch); mode=0;}
    } else {
      if (ch>=0x20) charcopy(ch); else (*funcarray[ch])(ch);
    }
  }
  exit(0);
}
-- 
___  __  ____________________________________________________________________
   |/  \   Jan Christiaan van Winkel                     jc@phoibos.cs.kun.nl
   |       Alternative e-mail addresses: jc@oreo.atcmp.nl and jc@atcmp.nl
__/ \__/ ____________________________________________________________________


-- 
| "The meek shall inherit the Earth --            |       hansk@aie.nl        |
|  The rest of us will go to the stars." -- R.H.  |  (old Henry Spencer sig)  |
Newsgroups: nlnet.misc