home *** CD-ROM | disk | FTP | other *** search
/ The Best of Mecomp Multimedia 1 / Mecomp-CD.iso / amiga / tools / misc / videotext5.41 / src / bildschirm.p next >
Encoding:
Text File  |  1997-05-17  |  23.6 KB  |  730 lines

  1. UNIT bildschirm; {$project vt }
  2. { Bildschirmausgaben zum Programm VideoText }
  3.  
  4. INTERFACE; FROM vt USES pagelist,decode,cct,sys;
  5.  
  6. VAR incomplete: Boolean;  { Seitenaufbau unterbrochen? }
  7.     concealed: Boolean;   { verdeckte Zeichen wirklich verdeckt? }
  8.     queue_input: String[10];
  9.     colht: Integer;   { muß zum spaltenweisen Blättern extern bekannt sein }
  10.     pgoffx: Integer;  { provisorische Hilfe für die IFF-Routine }
  11.  
  12. PROCEDURE cursoroff;
  13. PROCEDURE cursoron;
  14. PROCEDURE short_msg(s: str80; style: Byte);
  15. PROCEDURE add_msg(s: str80; style: Byte);
  16. PROCEDURE mark_queue(really: Boolean);
  17. PROCEDURE queue_me;
  18. PROCEDURE redraw_queue(job: Integer);
  19. FUNCTION pos_from_queue(x,y: Integer): Integer;
  20. PROCEDURE mark_list(really: Boolean);
  21. PROCEDURE redraw_list;
  22. PROCEDURE update_list(start: p_onepage; delta: Integer);
  23. FUNCTION page_from_list(x,y: Integer): p_onepage;
  24. PROCEDURE fileinfo;
  25. PROCEDURE test(active: Word);
  26. PROCEDURE writepage(seite: p_onepage, verdeckt: Boolean);
  27. FUNCTION number_from_page(x,y: Integer): Integer;
  28. PROCEDURE redraw_all;
  29. FUNCTION click_action(x,y: Integer): Char;
  30.  
  31. { ---------------------------------------------------------------------- }
  32.  
  33. IMPLEMENTATION;
  34.  
  35. {$opt q,s+,i+ } { keine Laufzeitprüfungen außer Stack und Feldindizes }
  36.  
  37. { Bildschirmlayout: }
  38. VAR screenw, screenht: Integer;
  39.     xp, yp: Integer;              { Position der Seite }
  40.     xt, yt: Integer;              { Position des Statusfeldes }
  41.     xs, ys, ws, sp_maxdisp: Integer;  { Position und Breite der Seitensuche }
  42.     xq, yq, head, tail: Integer;  { Pos. u. Aufteilung der Warteschlange }
  43.     xl, yl, cols, colw: Integer;  { Pos. und Gliederung der Seitenliste }
  44.     xm, ym, wm: Integer;          { Position und Breite der Meldezeile }
  45.     xf, xf2, xf3, xf4, yf, wf: Integer; { Position und Breite der Dateiinfo }
  46.  
  47. VAR listoffset: Integer;
  48.     lsizex: Integer;   { x-Position der Listengröße }
  49.     msglen: Integer;
  50.     umlaut,umltab: String[8];
  51.  
  52. PROCEDURE cursoroff;
  53. BEGIN
  54.   Write(#155'0 p');  { Cursor unsichtbar }
  55. END;
  56.  
  57. PROCEDURE cursoron;
  58. BEGIN
  59.   Write(#155' p');  { Cursor wieder sichtbar }
  60. END;
  61.  
  62. PROCEDURE short_msg{(s: str80; style: Byte)};   { normal: style=0 }
  63. BEGIN
  64.   msglen := 0;
  65.   add_msg(s, style);
  66. END;
  67.   
  68. PROCEDURE add_msg{(s: str80; style: Byte)};
  69. VAR i,j,l: Integer;
  70. BEGIN
  71.   IF ym<1 THEN Exit; { zu kleiner Bildschirm }
  72.   l := Length(s);
  73.   FOR i := 1 TO l DO BEGIN   { Umlaute ersetzen }
  74.     j := Pos(s[i],umlaut);
  75.     IF j>0 THEN s[i] := umltab[j];
  76.   END;
  77.   FOR i := l+1 TO wm-msglen DO s[i] := ' ';
  78.   IF msglen<wm THEN BEGIN
  79.     GotoXY(xm+msglen,ym);
  80.     s[wm-msglen+1] := #0;
  81.     IF style<>0 THEN Write(#155'0m');  { Mischen von Attributen verhindern }
  82.     Write(#155,style,'m',s);
  83.     msglen := msglen + l;
  84.   END;
  85. END;
  86.  
  87. PROCEDURE queue_entry(pg,sp: Integer);
  88. { besorgt v. a. die richtige Dekodierung der Unterseitennummer }
  89. BEGIN
  90.   Write(hexstr(pg,0));
  91.   CASE sp OF
  92.     -3: Write('/!');
  93.     -2: Write('/.');
  94.     -1: Write('/*');
  95.      0: ;
  96.     OTHERWISE IF sp>0 THEN Write('/',hexstr(sp,0))
  97.       ELSE Write('*',-10-sp); { auch '*0' möglich! }
  98.   END;
  99. END;
  100.  
  101. PROCEDURE mark_queue{(really: Boolean)};
  102. { Gibt die Position des Job-Markers <thisjob> als '>' am Bildschirm aus, }
  103. { <thisjob> kann Werte von <maxactive>-1 bis -<queued> annehmen. }
  104. { Für <really>=FALSE wird stattdessen ' ' ausgegeben. }
  105. VAR y,j: Integer;
  106.     special: Boolean;
  107. BEGIN
  108.   IF yq<1 THEN Exit; { zu kleiner Bildschirm }
  109.   special := False;
  110.   y := yq - thisjob - 2;
  111.   IF thisjob<0 THEN BEGIN
  112.     y := y + 2;
  113.     IF NOT fifo THEN y := y + 1;
  114.     IF (queued>=colht) AND (-thisjob>head) THEN BEGIN
  115.       { unvollständige Anzeige der Schlange }
  116.       IF -thisjob>queued-tail THEN
  117.         y := y + colht-1 - queued { zeigt auf hinteres Ende }
  118.       ELSE BEGIN
  119.         special := True;
  120.         y := y + thisjob + head + 1; { zeigt auf die '...' }
  121.         j := (firstinq - thisjob - 2) MOD qlen + 1;
  122.       END;
  123.     END;
  124.   END;
  125.   GotoXY(xq,y);
  126.   IF really THEN
  127.     Write('>')
  128.   ELSE 
  129.     Write(' '); 
  130.   IF special THEN BEGIN
  131.     Write('('); queue_entry(queue[j].pg,queue[j].sp); Write(')');
  132.   END;
  133. END;
  134.  
  135. PROCEDURE queue_me;
  136. { Die aktuelle Benutzereingabe am Ende (bzw. Anfang) der Warteschlange }
  137. { darstellen. }
  138. VAR s: String[10];
  139. BEGIN
  140.   IF yq<1 THEN Exit; { zu kleiner Bildschirm }
  141.   { den für Eingaben reservierten Platz ansteuern: }
  142.   IF NOT fifo THEN
  143.     GotoXY(xq+1,yq+1)
  144.   ELSE IF queued<colht THEN
  145.     GotoXY(xq+1,yq+1+queued)
  146.   ELSE
  147.     GotoXY(xq+1,yq+colht);
  148.   Write(#155'0m');
  149.   IF queued<qlen THEN BEGIN 
  150.     Write(queue_input,#155'7m');
  151.     IF Length(queue_input)<8 THEN BEGIN
  152.       s := '         '; s[8-Length(queue_input)] := #0;
  153.       Write(' '#155'0m',s);
  154.     END ELSE
  155.       Write(#8,queue_input[8]);
  156.   END;
  157. END;
  158.  
  159. PROCEDURE redraw_queue{(job: Integer)};
  160. { Gibt für job<0 die aktuelle Belegung der Warteschlange und der aktiven Jobs }
  161. { am Bildschirm aus, sonst wird nur der Job mit der angegebenen Nummer neu }
  162. { ausgegeben: interessant ist dabei vor allem der Status der eingelesenen }
  163. { Unterseiten. }
  164. VAR i,j,y,max: Integer;
  165. BEGIN
  166.   IF yq<1 THEN Exit; { zu kleiner Bildschirm }
  167.   GotoXY(xs,ys); Write(#155'0m Seitensuche:');
  168.   FOR j := 0 TO maxactive-1 DO
  169.     IF (job<0) OR (j=job) THEN WITH activejobs[j] DO BEGIN
  170.       GotoXY(xs,ys+maxactive-j);
  171.       Write(Copy(blank40,1,ws)); { nicht das Testfeld überschreiben! }
  172.       GotoXY(xs+1,ys+maxactive-j);
  173.       IF pg=0 THEN Write('---')
  174.       ELSE BEGIN
  175.         queue_entry(pg,sp);
  176.         Write('  ');
  177.         IF sp_check[0] THEN Write('+');
  178.         IF sp_max>0 THEN     { echte Unterseiten eingetroffen }
  179.           IF (sp>0) OR (sp IN [-3..-1]) THEN  { zu einer Einzelanforderung? }
  180.             Write('+')
  181.           ELSE BEGIN
  182.             max := get_bcd(sp_max); IF max>sp_maxdisp THEN max := sp_maxdisp-2;
  183.             Write('(');
  184.             FOR i := 1 TO max DO
  185.               IF sp_check[i] THEN Write('+') ELSE Write('-');
  186.             IF get_bcd(sp_max)>max THEN Write('...') ELSE Write(')');
  187.           END;
  188.       END;
  189.     END;
  190.   GotoXY(xq,yq);
  191.   IF fifo THEN Write(' Jobs:') ELSE Write(' Jobs!');
  192.   IF job<0 THEN BEGIN
  193.     y := yq + 1;
  194.     IF fifo THEN y := y + colht - 1;
  195.     GotoXY(xq,y); Write('         ');
  196.     FOR j := 1 TO colht-1 DO BEGIN
  197.       y := yq+j; IF NOT fifo THEN y := y + 1;
  198.       GotoXY(xq,y); Write('         ');
  199.       IF j<=queued THEN BEGIN
  200.         GotoXY(xq+1,y);
  201.         i := (firstinq + j - 2) MOD qlen + 1;
  202.         IF (queued>=colht) AND (j>head) THEN
  203.           i := (firstinq + queued + j - colht - 1) MOD qlen + 1;
  204.         IF (queued>=colht) AND (j=head+1) THEN
  205.           Write('...')
  206.         ELSE
  207.           queue_entry(queue[i].pg,queue[i].sp);
  208.       END;
  209.     END; { Ende FOR-Schleife }
  210.     queue_me;
  211.   END;
  212.   mark_queue(True);
  213. END;
  214.  
  215. FUNCTION pos_from_queue{(x,y: Integer): Integer};
  216. { wurde auf eine Nummer in der Warteschlange geklickt? }
  217. BEGIN
  218.   pos_from_queue := maxactive;  { unmöglicher Wert }
  219.   IF yq<1 THEN Exit; { zu kleiner Bildschirm }
  220.   IF (x<xq) OR (x>xq+8) THEN Exit;
  221.   IF (y>ys) AND (y<=ys+maxactive) THEN
  222.     pos_from_queue := maxactive + ys - y { Position in der Seitensuche }
  223.   ELSE BEGIN
  224.     y := y - yq; IF NOT fifo THEN Dec(y);
  225.     IF (y>0) AND (y<colht) AND(y<=queued) THEN
  226.       IF (queued<colht) OR (y<=head) THEN
  227.         pos_from_queue := -y
  228.       ELSE
  229.         pos_from_queue := -(y-colht+queued+1);
  230.   END;
  231. END;
  232.  
  233. { Der Ärger mit der Seitenliste ... }
  234.  
  235. FUNCTION adjust_offset: Integer;
  236. { Da die Seitenliste meist nicht ganz auf den Bildschirm paßt, gibt ein }
  237. { Offset an, ab wo sie sichtbar ist, dieser <listoffset> wird hier neu }
  238. { berechnet. Der Rückgabewert sagt, um wieviele Spalten die Liste (falls }
  239. { bereits angezeigt) verschoben werden muß. (>0: rechts kommen Spalten dazu) }
  240. { Besteht die Liste aus nur einer Spalte, gibt der Rückgabewert an, wie }
  241. { weit sie vertikal gescrollt werden muß. (>0: unten kommen Zeilen dazu) }
  242. VAR nr,delta: Integer;
  243. BEGIN
  244.   nr := posn_in_list(thispage);   { wo steht der Zeiger? }
  245.   delta := 0;
  246.   IF cols>1 THEN BEGIN
  247.     WHILE nr<listoffset DO BEGIN
  248.       listoffset := listoffset-colht; Dec(delta);  END;
  249.     WHILE nr-listoffset>=cols*colht DO BEGIN
  250.       listoffset := listoffset+colht; Inc(delta);  END;
  251.   END ELSE BEGIN
  252.     IF nr<listoffset THEN delta := nr-listoffset;
  253.     IF nr>=listoffset+colht THEN delta := nr-(listoffset+colht-1);
  254.     listoffset := listoffset + delta;
  255.   END;
  256.   adjust_offset := delta;
  257. END;
  258.  
  259. PROCEDURE listentry(seite: p_onepage; nr: Integer);
  260. { Einen Listeneintrag erzeugen, von dem seine Nummer im sichtbaren Bereich }
  261. { der Liste bekannt ist. }
  262. VAR i,x,y: Integer;
  263.     s: String[20];
  264. BEGIN
  265.   x := xl+colw*(nr DIV colht); y := yl+1+nr MOD colht;
  266.   GotoXY(x,y); Write(#155'0m');
  267.   s := '';
  268.   IF seite<>Nil THEN BEGIN
  269.     s := ' '+hexstr(seite^.pg,0)+'/'+hexstr(seite^.sp,0);
  270.     IF (seite^.cbits AND PF_LOCAL<>0) THEN 
  271.       Write(#155'7m') { Invers }
  272.     ELSE IF NOT seite^.dejavu THEN 
  273.       Write(#155'1m'); { Fett }
  274.     IF (seite^.cbits AND PF_PSEUDO<>0) THEN 
  275.       Write(#155'2m'); { Hilite }
  276.   END;
  277.   i := Length(s);
  278.   WHILE i<colw DO BEGIN Inc(i); s[i] := ' '; END;
  279.   s[i+1] := #0;
  280.   Write(s);
  281. END;
  282.  
  283. PROCEDURE redraw_column(col: Integer);
  284. { gibt eine Spalte der Seitenliste aus }
  285. VAR i: Integer;
  286.     hilf: p_onepage;
  287. BEGIN
  288.   hilf := page_on_posn(listoffset+(col-1)*colht);
  289.   FOR i := 1 TO colht DO BEGIN
  290.     listentry(hilf,(i-1)+(col-1)*colht);
  291.     IF hilf<>Nil THEN hilf := hilf^.next;
  292.   END;
  293. END;
  294.  
  295. PROCEDURE redraw_rows(rows: Integer);
  296. { gibt die ersten <rows> bzw. die letzten <-rows> Zeilen der Seitenliste }
  297. { aus, nicht ganz trivial }
  298. VAR i,j: Integer;
  299.     hilf: p_onepage;
  300. BEGIN
  301.   hilf := page_on_posn(listoffset);
  302.   FOR i := 1 TO cols DO
  303.     FOR j := 1 TO colht DO BEGIN
  304.     IF (j<=rows) OR (j>colht+rows) THEN
  305.       listentry(hilf,(j-1)+(i-1)*colht);
  306.     IF hilf<>Nil THEN hilf := hilf^.next;
  307.   END;
  308. END;
  309.  
  310. PROCEDURE mark_list{(really: Boolean)};
  311. { Gibt die Position des Seiten-Markers <thispage> am Bildschirm aus, für }
  312. { <really>=FALSE wird die Markierung dagegen aufgehoben. }
  313. { Scrollt die Liste auch weiter, falls nötig. }
  314. VAR nr,i,x,y: Integer;
  315.     dx: Integer;
  316. BEGIN
  317.   IF yl<1 THEN Exit; { zu kleiner Bildschirm }
  318.   { scrollen? }
  319.   dx := adjust_offset;
  320.   IF cols>1 THEN BEGIN
  321.     FOR i := cols DOWNTO 1 DO BEGIN
  322.       IF dx>=i THEN  scroll_text(yl+1,yl+colht,xl,xl+cols*colw-1,0,colw);
  323.       IF dx<=-i THEN  scroll_text(yl+1,yl+colht,xl,xl+cols*colw-1,0,-colw);
  324.     END;
  325.     FOR i := 1 TO cols DO
  326.       IF (i+dx>cols) OR (i+dx<1) THEN
  327.         redraw_column(i);
  328.   END ELSE BEGIN  { 1 Spalte vertikal scrollen }
  329.     IF Abs(dx)<colht THEN FOR i := colht DOWNTO 1 DO BEGIN
  330.       IF dx>=i THEN  scroll_text(yl+1,yl+colht,xl,xl+colw-1,1,0);
  331.       IF dx<=-i THEN  scroll_text(yl+1,yl+colht,xl,xl+colw-1,-1,0);
  332.     END;
  333.     IF dx<>0 THEN redraw_rows(-dx);
  334.   END;
  335.   IF thispage<>Nil THEN thispage^.dejavu := True;
  336.   nr := posn_in_list(thispage) - listoffset;   { wo steht der Zeiger? }
  337.   listentry(thispage,nr);
  338.   x := xl+colw*(nr DIV colht); y := yl+1+nr MOD colht;
  339.   GotoXY(x,y); 
  340.   IF really THEN
  341.     Write('>')
  342.   ELSE 
  343.     Write(' '); 
  344. END;
  345.  
  346. PROCEDURE redraw_list;
  347. { aktualisiert die gesamte Seitenliste }
  348. VAR i: Integer;
  349.     hilf: p_onepage;
  350. BEGIN
  351.   IF yl<1 THEN Exit; { zu kleiner Bildschirm }
  352.   IF adjust_offset<>0 THEN; { Wert ist egal }
  353.   GotoXY(xp-6,yl); Write(#155'0m',listsize:5);
  354.   lsizex := xp-1-Length(IntStr(listsize)); 
  355.   GotoXY(xl,yl); Write(' Seiten:');
  356.   hilf := page_on_posn(listoffset);
  357.   FOR i := 0 TO cols*colht-1 DO BEGIN
  358.     listentry(hilf,i);
  359.     IF hilf<>Nil THEN hilf := hilf^.next;
  360.   END;
  361.   mark_list(True);
  362. END;
  363.  
  364. PROCEDURE update_list{(start: p_onepage; delta: Integer)};
  365. { Es wurden Seiten in die Liste eingefügt (delta>0) bzw. entfernt (delta<0). }
  366. { <start> ist die erste Seite, die sich dadurch geändert hat. }
  367. { delta=0 ist auch zulässig, z. B. um für eine aktualisierte Nummer wieder }
  368. { Fettdruck zu erzwingen. }
  369. VAR i,nr: Integer;
  370.     hilf: p_onepage;
  371. BEGIN
  372.   IF yl<1 THEN Exit; { zu kleiner Bildschirm }
  373.   lsizex := xp-1-Length(IntStr(listsize));
  374.   GotoXY(lsizex-1,yl); Write(#155'0m ',listsize);
  375.   { wo auf dem Bildschirm ist die bezeichnete Seite? }
  376.   nr := posn_in_list(start) - listoffset;
  377.   IF delta=0 THEN BEGIN
  378.     IF nr IN [0..cols*colht-1] THEN listentry(start,nr);
  379.     Exit;
  380.   END;
  381.   { ein paar Spalten komplett scrollen, eine nur zum Teil }
  382.   FOR i := 1 TO cols DO BEGIN
  383.     IF (i-1)*colht>=nr THEN
  384.       scroll_text(yl+1,yl+colht,xl+(i-1)*colw,xl+i*colw-1,-delta,0)
  385.     ELSE IF i*colht>=nr+Abs(delta) THEN
  386.       scroll_text(yl+1+nr MOD colht,yl+colht,xl+(i-1)*colw,xl+i*colw-1,-delta,0)
  387.   END;
  388.   hilf := start;
  389.   FOR i := 0 TO delta DO BEGIN { einer zuviel, ist aber Absicht ... }
  390.     IF nr+i IN [0..cols*colht-1] THEN listentry(hilf,nr+i);
  391.     IF hilf<>Nil THEN hilf := hilf^.next;
  392.   END;
  393.   redraw_rows(delta);
  394.   { '>' neu setzten, hat evtl. sogar den Bildschirm verlassen: }
  395.   mark_list(True);
  396. END;
  397.  
  398. FUNCTION page_from_list{(x,y: Integer): p_onepage};
  399. { zu einer angeklickten Zeichenposition die Seite herausfinden }
  400. VAR nr: Integer;
  401.     hilf: p_onepage;
  402. BEGIN
  403.   page_from_list := Nil;
  404.   IF yl<1 THEN Exit; { zu kleiner Bildschirm }
  405.   IF (y IN [yl+1..yl+colht]) AND (x IN [xl-2..xl+cols*colw+2]) THEN BEGIN
  406.     nr := listoffset + y - (yl+1) + colht*(Round((x-xl)/colw+0.5)-1);
  407.     page_from_list := page_on_posn(nr);
  408.   END;
  409. END;
  410.  
  411. PROCEDURE fileinfo;
  412. VAR l,space: Integer;
  413. BEGIN
  414.   IF yf<1 THEN Exit; { zu kleiner Bildschirm }
  415.   GotoXY(xf,yf);
  416.   Write(#155'0mDatei ('); xf2 := xf + 6;
  417.   xf3 := xf2 + 6;
  418.   IF asciifile THEN BEGIN  Write('ASCII): '); xf3 := xf3 + 3; END
  419.     ELSE Write('VT): ');
  420.   space := screenw - xf3; IF withicon THEN space := space - 10;
  421.   l := Length(outputname);
  422.   IF l>space THEN Write(#155'2m...',Copy(outputname,l-space+4,space-3))
  423.     ELSE Write(#155'2m',outputname);
  424.   IF l>space THEN xf4 := xf3 + space ELSE xf4 := xf3 + l;
  425.   IF withicon THEN Write(#155'0m, mit Icon');
  426.   ClrEoL;
  427. END;
  428.  
  429. PROCEDURE test{(active: Word)};
  430. { Decodertest, sollte aus einer Schleife heraus aufgerufen werden. }
  431. { Steuerbits: %00001 = Uhrzeit und Status abfragen }
  432. {             %00010 = Sendernamen anzeigen }
  433. {             %10000 = regulärer Aufruf, leere Felder ignorieren }
  434. VAR stat: Byte;
  435.     i: Integer;
  436.     zeit: str80;
  437.     ch: char;
  438.     tag,min,tic: Long;
  439. PROCEDURE zweistellig(x: Integer);  BEGIN  Write(x DIV 10, x MOD 10);  END;
  440. BEGIN
  441.   IF yt<1 THEN Exit; { zu kleiner Bildschirm }
  442.   GotoXY(xt,yt);
  443.   Write(#155'0mStatus:');
  444.   IF (active AND $11)=0 THEN BEGIN
  445.     Write(Copy(blank40,1,17)); Write(#155,'2m');
  446.     FOR i := 1 TO 2 DO BEGIN
  447.       GotoXY(xt,yt+i); Write(Copy(blank40,1,24));
  448.     END;
  449.   END;
  450.   IF (active AND $12)=0 THEN BEGIN
  451.     GotoXY(xt,yt+3); Write(Copy(blank40,1,24)); 
  452.   END;
  453.   IF (active AND $11=0) OR ((active AND 1)<>0) THEN BEGIN
  454.     GotoXY(xt+10,yt); Write('Bus:');
  455.     GotoXY(xt+15,yt+1); Write('AV:');
  456.     GotoXY(xt+15,yt+2); Write('VT:');
  457.     GotoXY(xt,yt+1); Write('OS:');
  458.     GotoXY(xt,yt+2); Write('VT:');
  459.   END;
  460.   IF (active AND 1)<>0 THEN BEGIN
  461.     Write(#155,'2m');
  462.     stat := VTstat;
  463.     GotoXY(xt+15,yt);
  464.     IF i2c_status=0 THEN
  465.       Write('OK  ') ELSE Write('Err',i2c_status);
  466.     FOR i := 1 TO 2 DO BEGIN
  467.       GotoXY(xt+19,yt+i);
  468.       IF i2c_status=0 THEN
  469.         IF (stat AND i)<>0 THEN Write('ja  ')  ELSE  Write('nein')
  470.       ELSE
  471.         Write('    ')
  472.     END;
  473.     { Zeit aus dem VT-Seitenspeicher abfragen: }
  474.     gettime(zeit);
  475.     GotoXY(xt+4,yt+2); Write(zeit);
  476.     { zum Vergleich: Amiga-Zeit }
  477.     telltime(tag,min,tic);
  478.     GotoXY(xt+4,yt+1);
  479.     zweistellig(min DIV 60); Write(':');
  480.     zweistellig(min MOD 60); Write(':');
  481.     zweistellig(tic DIV 50);
  482.   END;
  483.   IF (active AND 2)<>0 THEN BEGIN
  484.     { Sendername: }
  485.     gethead(zeit);
  486.     GotoXY(xt,yt+3); Write(#155,'2m',zeit);
  487.   END;
  488.   Write(#155'0m');
  489. END;
  490.  
  491. PROCEDURE writepage{(seite: p_onepage, verdeckt: Boolean)};
  492. { Seite am Bildschirm ausgeben }
  493. VAR zeile,i,i0,i1,j,j0: Integer;
  494.     farbe,farbe0: Word;
  495.     out: bigstring;
  496.     x: Byte;
  497.     s,attrib: str80;
  498.     dblheight,rastergfx,special: Boolean;
  499.     normal: String[10];
  500. BEGIN
  501.   incomplete := True;
  502.   i0 := 0; i1 := 24;
  503.   visblpage := seite;
  504.   concealed := verdeckt;
  505.   normal := #155'0;3'+colperms[7]+';4'+colperms[0]+'m'; { weiß auf schwarz }
  506.   dblheight := False; rastergfx := False;
  507.   IF seite<>Nil THEN
  508.     IF seite^.pg>0 THEN 
  509.       seite^.chars[0] := 2  { Seitennummer zunächst grün }
  510.     ELSE BEGIN
  511.       { Mieser Trick, um eine Seite bestimmen zu lassen, daß nur ein Teil }
  512.       { ihrer Zeilen ausgegeben wird (z. B. steht 0/104 für Zeile 1 bis 4): }
  513.       i0 := seite^.sp DIV 100; i1 := seite^.sp MOD 100;
  514.       IF i1>24 THEN i1 := 24;
  515.     END;
  516.   FOR i := i0 TO i1 DO BEGIN
  517.     zeile := i MOD 24;
  518.     IF i=24 THEN BEGIN
  519.       { 1. Zeile nochmal, mit weißer Seitennummer: }
  520.       IF seite<>Nil THEN IF seite^.pg>0 THEN
  521.         seite^.chars[0] := 7;
  522.       dblheight := False;
  523.     END;
  524.     IF dblheight THEN
  525.       { auf eine doppelthohe Zeile folgt nur eine leere Zeile }
  526.       dblheight := False
  527.     ELSE BEGIN
  528.       { normale Zeile ausgeben }
  529.       IF seite<>Nil THEN
  530.         decode_line(seite, zeile, verdeckt, out, attrib, dblheight, rastergfx)
  531.       ELSE
  532.         out := blank40;
  533.       GotoXY(xp,yp+zeile); 
  534.       Write(normal,out); IF screenw>40 THEN Write(normal,' ');
  535.       IF rastergfx THEN BEGIN  { Zeile, die gerasterte Grafikzeichen enthält }
  536.         special := False; farbe := 0;
  537.         FOR j := 0 TO 39 DO BEGIN  { zu rasternde Abschnitte suchen }
  538.           farbe0 := farbe; farbe := Ord(attrib[j+1]);
  539.           IF (farbe<>farbe0) AND special THEN BEGIN
  540.             raster_line(yp+zeile,xp+j0,xp+j-1,farbe0 AND 7);
  541.             j0 := j; special := (farbe AND 16<>0);
  542.           END;
  543.           IF (farbe AND 16<>0) AND NOT special THEN BEGIN
  544.             j0 := j; special := True;
  545.           END;
  546.         END;
  547.         IF special THEN
  548.           raster_line(yp+zeile,xp+j0,xp+39,farbe0 AND 7);
  549.       END;
  550.       IF zeile=23 THEN dblheight := False; { unterste Zeile nie doppelthoch! }
  551.       IF dblheight THEN BEGIN   { Handhabung doppelthoher Zeilen }
  552.         special := False;
  553.         FOR j := 1 TO Length(out) DO BEGIN   { alles außer den ANSI-Codes }
  554.           { entfernen -> erzeugt Kopie der Hintergrundfarben der Zeile }
  555.           IF out[j] = #155 THEN special := True;
  556.           IF NOT special THEN out[j] := ' ';
  557.           IF out[j] = 'm' THEN special := False;
  558.         END;
  559.         GotoXY(xp,yp+zeile+1); 
  560.         Write(normal,out); IF screenw>40 THEN Write(normal,' ');
  561.         special := False;
  562.         FOR j := 0 TO 39 DO   { doppelthohe Abschnitte suchen }
  563.           CASE seite^.chars[40*zeile+j] OF
  564.             13: BEGIN j0 := j; special := True; END;
  565.             12: IF special THEN BEGIN
  566.                 stretch_line(yp+zeile,xp+j0,xp+j); special := False;
  567.               END;
  568.             OTHERWISE;
  569.           END;
  570.         IF special THEN
  571.           stretch_line(yp+zeile,xp+j0,xp+39);
  572.       END;
  573.     END;
  574.     event_scan(False); IF newevent THEN  Exit;
  575.   END;
  576.   incomplete := False;   { Seite komplett }
  577. END;
  578.  
  579. FUNCTION number_from_page{(x,y: Integer): Integer};
  580. { versucht zu einer angeklickten Bildschirmposition herauszufinden, auf }
  581. { was für eine Nummer geklickt wurde }
  582. { Ergebnis ist eine BCD-Zahl, -1: keine Nummer gefunden }
  583. VAR i,j,j0,n,m: Integer;
  584.     ok,special,hidden: Boolean;
  585. BEGIN
  586.   number_from_page := -1;
  587.   IF NOT ((x IN [xp..xp+39]) AND (y IN [yp..yp+23])) OR (visblpage=Nil) THEN 
  588.     Exit;
  589.   n := -1;
  590.   IF (visblpage^.cbits AND PF_ISMAP)<>0 THEN BEGIN
  591.     { Sonderseite: TOP-Belegungsschema }
  592.     i := 40*(y-yp); { 1. Zeichen der Zeile }
  593.     j0 := 0;  { vorangehenden Doppelpunkt finden }
  594.     FOR j := 3 TO x-xp-2 DO
  595.       IF visblpage^.chars[i+j]=Ord(':') THEN j0 := j;
  596.     IF j0>0 THEN BEGIN { Zahl vor dem Doppelpunkt auswerten }
  597.       n := 0;
  598.       FOR j := j0-3 TO j0-1 DO
  599.         n := (n SHL 4) + visblpage^.chars[i+j]-48;
  600.       IF x-xp-2 < j0+10 THEN
  601.         n := n + (x-xp-2-j0)
  602.       ELSE
  603.         n := -1;
  604.     END;
  605.   END;
  606.   IF n<0 THEN BEGIN  { noch nichts gefunden? }
  607.     i := 40*(y-yp); { 1. Zeichen der Zeile }
  608.     { Sonderfall: untere Hälfte einer doppelthohen Zeile? }
  609.     special := False;
  610.     IF y>yp THEN
  611.       FOR j := -40 TO -1 DO
  612.         IF visblpage^.chars[i+j]=13 THEN special := True;
  613.     IF special THEN i := i-40;  { eine Zeile höher gehen }
  614.     { versuchen eine Zahl zu lesen, die (x,y) enthält }
  615.     ok := True; j0 := x-xp;
  616.     FOR j := x-xp DOWNTO 0 DO BEGIN
  617.       IF NOT (visblpage^.chars[i+j] IN [48..57]) THEN ok := False;
  618.       IF ok THEN j0 := j;
  619.     END;
  620.     ok := True; n := 0; m := 0;
  621.     FOR j := j0 TO 39 DO BEGIN
  622.       IF NOT (visblpage^.chars[i+j] IN [48..57]) THEN ok := False;
  623.       IF ok THEN BEGIN
  624.         n := (n SHL 4) + visblpage^.chars[i+j]-48; Inc(m);
  625.       END;                    
  626.     END;
  627.     IF m=0 THEN n := -1;  { keine Ziffern gefunden }
  628.     { die gefundene Zahl ist aber möglicherweise gar nicht sichtbar! }
  629.     special := False; hidden := False;
  630.     FOR j := 0 TO j0 DO
  631.       IF visblpage^.chars[i+j]<32 THEN BEGIN
  632.         hidden := False;
  633.         CASE visblpage^.chars[i+j] OF
  634.           0..7: special := False;
  635.           16..23: special := True;
  636.           24: hidden := True;
  637.           OTHERWISE;
  638.         END;
  639.       END;
  640.     IF special OR (hidden AND concealed) THEN n := -1;
  641.   END;
  642.   number_from_page := n;
  643. END;
  644.  
  645.  
  646. PROCEDURE do_layout;
  647. { ausgehend von der Bildschirmgröße Position der diversen Sachen festlegen }
  648. BEGIN
  649.   xp := screenw-40; yp := 1;   { Seite }
  650.   IF xp<1 THEN xp := 1;
  651.   xt := xp-24; yt := 2;  { Statusfeld }
  652.   IF screenht>30 THEN BEGIN
  653.     xt := xp; yt := yp+25;
  654.   END;
  655.   IF xt<1 THEN yt := 0;  { -> nicht darstellen! }
  656.   xs := 1; ys := 1; ws := xt-1; IF yt<1 THEN ws := xp-1;  { Seitensuche }
  657.   sp_maxdisp := ws-9;
  658.   IF ws<9 THEN ys := 0;  { -> nicht darstellen! }
  659.   xq := 1; yq := ys+6; colht := screenht-yq-4;  { Warteschlange }
  660.   head := (colht-1) DIV 2; tail := colht-head-2; 
  661.   IF ws<9 THEN yq := 0;  { -> nicht darstellen! }
  662.   colw := 9;
  663.   xl := xq+colw; yl := yq; cols := (xp-xl) DIV colw; { Seitenliste }
  664.   IF cols<1 THEN yl := 0; { -> nicht darstellen! }
  665.   xm := 1; ym := screenht-2; wm := xp-1;    { Meldezeile }
  666.   IF ym>yp+28 THEN wm := screenw;
  667.   IF wm>79 THEN wm := 79; 
  668.   IF wm<1 THEN ym := 0;  { -> nicht darstellen! }
  669.   xf := 1; yf := screenht; wf := screenw; { Dateiinfo }
  670.   pgoffx := xp-1;
  671. END;
  672.  
  673. PROCEDURE redraw_all;
  674. { kompletter Neuaufbau des Bildschirms, inklusive clrscr }
  675. VAR s: str80;
  676.     i: Integer;
  677.     c: Char;
  678. BEGIN
  679.   Write(#27'c');  { Console-Reset, wichtig um die Fontgröße anzupassen }
  680.   cursoroff;
  681.   { Fensterausmaße abfragen: }
  682.   Write(#155' q'); s := '';
  683.   REPEAT
  684.     c := ReadCon(Con); s := s + c;
  685.   UNTIL c=#0;
  686.   i := 1; REPEAT Inc(i) UNTIL s[i]=';'; REPEAT Inc(i) UNTIL s[i]=';';
  687.   Inc(i); screenht := 0;
  688.   WHILE s[i] IN ['0'..'9'] DO BEGIN
  689.     screenht := 10*screenht+Ord(s[i])-48; Inc(i); END;
  690.   Inc(i); screenw := 0;
  691.   WHILE s[i] IN ['0'..'9'] DO BEGIN
  692.     screenw := 10*screenw+Ord(s[i])-48; Inc(i); END;
  693.   do_layout; { und Abmessungen auswerten }
  694.   redraw_queue(-1); test(0);
  695.   redraw_list; fileinfo;
  696.   writepage(thispage,True);
  697. END;
  698.  
  699. FUNCTION click_action{(x,y: Integer): Char};
  700. { Ein paar bestimmte Sachen, die man anklicken kann }
  701. BEGIN
  702.   click_action := ' ';
  703.   IF (y=yt) AND (x IN [xt..xt+6]) THEN click_action := 'T'; { "Status" }
  704.   IF (y=ys) AND (x IN [xs+1..xs+12]) THEN click_action := 'S'; { "Seitensuche" }
  705.   IF (y=yq) AND (x IN [xq+1..xq+5]) THEN click_action := 'J'; { "Jobs" }
  706.   IF (y=yl) AND (x IN [xl+1..xl+6]) THEN click_action := 'L'; { "Seiten" }
  707.   IF (y=yl) AND (x IN [lsizex..xp-2]) THEN click_action := 'K'; { Löschen }
  708.   IF (y=yf) THEN BEGIN
  709.     IF x IN [xf2..xf3-3] THEN click_action := 'F'; { Format }
  710.     IF x IN [xf3..xf4-1] THEN click_action := 'N'; { Dateiname }
  711.     IF x>=xf4 THEN click_action := 'I'; { Icon? }
  712.   END;
  713.   IF (x>=xp) THEN CASE y-yp OF
  714.       0..7: click_action := '-'; { oberes Seitendrittel }
  715.       8..15: click_action := '0'; { Seitenmitte }
  716.       16..23: click_action := '+'; { unteres Seitendrittel }
  717.       OTHERWISE;
  718.     END;
  719. END;
  720.  
  721. BEGIN { Initialisierungsteil }
  722.   listoffset := 0;
  723.   incomplete := False;
  724.   concealed := True;
  725.   queue_input := '';
  726.   screenw := 80; screenht := 26; do_layout; { dumme Default-Werte }
  727.   umlaut := 'äöüßÄÖÜ'; umltab := '{|}~[\]';
  728. END.
  729.  
  730.