UNIT bildschirm; {$project vt } { Bildschirmausgaben zum Programm VideoText } INTERFACE; FROM vt USES pagelist,decode,cct,sys; CONST colht=15; VAR jobcursor: Boolean; { >Markierung in der Job- oder in der Seitenliste? } incomplete: Boolean; { Seitenaufbau unterbrochen? } concealed: Boolean; { verdeckte Zeichen wirklich verdeckt? } queue_input: String[10]; PROCEDURE cursoroff; PROCEDURE cursoron; PROCEDURE mainline; PROCEDURE mark_queue(really: Boolean); PROCEDURE queue_me; PROCEDURE redraw_queue(job: Integer); FUNCTION pos_from_queue(x,y: Integer): Integer; PROCEDURE mark_list(really: Boolean); PROCEDURE redraw_list; PROCEDURE update_list(start: p_onepage; delta: Integer); FUNCTION page_from_list(x,y: Integer): p_onepage; PROCEDURE hilite_crsr; PROCEDURE fileinfo; PROCEDURE test(active: Boolean); PROCEDURE writepage(seite: p_onepage, verdeckt: Boolean); FUNCTION number_from_page(x,y: Integer): Integer; PROCEDURE redraw_all; FUNCTION click_action(x,y: Integer): Char; { ---------------------------------------------------------------------- } IMPLEMENTATION; {$opt q,s+,i+ } { keine Laufzeitprüfungen außer Stack und Feldindizes } CONST head=7; tail=6; { Aufteilung der Warteschlange } sp_maxdisp=15; VAR listoffset: Integer; fix1,fix2,fix3,fix4: Integer; { fileinfo-x-Positionen } lsizex: Integer; { x-Position der Listengröße } PROCEDURE cursoroff; BEGIN Write(#155'0 p'); { Cursor unsichtbar } END; PROCEDURE cursoron; BEGIN Write(#155' p'); { Cursor wieder sichtbar } END; PROCEDURE mainline; BEGIN GotoXY(1,24); Write(#155'0m',Copy(blank40,1,39)); GotoXY(1,24); END; PROCEDURE queue_entry(pg,sp: Integer); { besorgt v. a. die richtige Dekodierung der Unterseitennummer } BEGIN Write(hexstr(pg,0)); CASE sp OF -3: Write('/!'); -2: Write('/.'); -1: Write('/*'); 0: ; OTHERWISE IF sp>0 THEN Write('/',hexstr(sp,0)) ELSE Write(sp+10); END; END; PROCEDURE mark_queue{(really: Boolean)}; { Gibt die Position des Job-Markers als '>' am Bildschirm aus, } { kann Werte von -1 bis - annehmen. } { Für =FALSE wird stattdessen ' ' ausgegeben. } CONST x0=1; y0=1; VAR y,j: Integer; special: Boolean; BEGIN special := False; y := y0 + maxactive - thisjob; IF thisjob<0 THEN BEGIN y := y + 2; IF NOT fifo THEN y := y + 1; IF (queued>=colht) AND (-thisjob>head) THEN BEGIN { unvollständige Anzeige der Schlange } IF -thisjob>queued-tail THEN y := y + colht-1 - queued { zeigt auf hinteres Ende } ELSE BEGIN special := True; y := y + thisjob + head + 1; { zeigt auf die '...' } j := (firstinq - thisjob - 2) MOD qlen + 1; END; END; END; GotoXY(x0,y); IF really THEN BEGIN IF NOT jobcursor THEN Write(#155,'2m'); Write('>'#155'0m'); END ELSE Write(' '); IF special THEN BEGIN Write('('); queue_entry(queue[j].pg,queue[j].sp); Write(')'); END; END; PROCEDURE queue_me; { Die aktuelle Benutzereingabe am Ende (bzw. Anfang) der Warteschlange } { darstellen. } CONST x0=1; y0=1; VAR s: String[10]; BEGIN { den für Eingaben reservierten Platz ansteuern: } IF NOT fifo THEN GotoXY(x0+1,y0+3+maxactive) ELSE IF queued0 THEN { echte Unterseiten eingetroffen } IF (sp>0) OR (sp IN [-3..-1]) THEN { zu einer Einzelanforderung? } Write('+') ELSE BEGIN max := get_bcd(sp_max); IF max>sp_maxdisp THEN max := sp_maxdisp-2; Write('('); FOR i := 1 TO max DO IF sp_check[i] THEN Write('+') ELSE Write('-'); IF get_bcd(sp_max)>max THEN Write('...') ELSE Write(')'); END; END; END; GotoXY(x0,y0+2+maxactive); IF fifo THEN Write(' Jobs:') ELSE Write(' Jobs!'); IF job<0 THEN BEGIN y := y0 + 3 + maxactive; IF fifo THEN y := y + colht - 1; GotoXY(x0,y); Write(' '); FOR j := 1 TO colht-1 DO BEGIN y := j+y0+2+maxactive; IF NOT fifo THEN y := y + 1; GotoXY(x0,y); Write(' '); IF j<=queued THEN BEGIN GotoXY(x0+1,y); i := (firstinq + j - 2) MOD qlen + 1; IF (queued>=colht) AND (j>head) THEN i := (firstinq + queued + j - colht - 1) MOD qlen + 1; IF (queued>=colht) AND (j=head+1) THEN Write('...') ELSE queue_entry(queue[i].pg,queue[i].sp); END; END; { Ende FOR-Schleife } queue_me; END; mark_queue(True); END; FUNCTION pos_from_queue{(x,y: Integer): Integer}; { wurde auf eine Nummer in der Warteschlange geklickt? } CONST x0=1; y0=1; BEGIN pos_from_queue := maxactive; { unmöglicher Wert } IF (xx0+8) THEN Exit; IF (y>y0) AND (y<=y0+maxactive) THEN pos_from_queue := maxactive + y0 - y { Position in der Seitensuche } ELSE BEGIN y := y - y0 - maxactive - 2; IF NOT fifo THEN Dec(y); IF (y>0) AND (y wird hier neu } { berechnet. Der Rückgabewert sagt, um wieviele Spalten die Liste (falls } { bereits angezeigt) verschoben werden muß. (>0: rechts kommen Spalten dazu) } VAR nr,delta: Integer; BEGIN nr := posn_in_list(thispage); { wo steht der Zeiger? } delta := 0; WHILE nr=cols*colht DO BEGIN listoffset := listoffset+colht; Inc(delta); END; adjust_offset := delta; END; PROCEDURE listentry(seite: p_onepage; nr: Integer); { Einen Listeneintrag erzeugen, von dem seine Nummer im sichtbaren Bereich } { der Liste bekannt ist. } VAR i,x,y: Integer; s: String[20]; BEGIN x := x0+colw*(nr DIV colht); y := y0+1+nr MOD colht; GotoXY(x,y); Write(#155'0m'); s := ''; IF seite<>Nil THEN BEGIN s := ' '+hexstr(seite^.pg,0)+'/'+hexstr(seite^.sp,0); IF NOT seite^.dejavu THEN Write(#155'1m'); { Fettdruck } END; i := Length(s); WHILE iNil THEN hilf := hilf^.next; END; END; PROCEDURE mark_list{(really: Boolean)}; { Gibt die Position des Seiten-Markers am Bildschirm aus, für } { =FALSE wird die Markierung dagegen aufgehoben. } { Scrollt die Liste auch weiter, falls nötig. } VAR nr,i,x,y: Integer; dx: Integer; BEGIN { scrollen? } dx := adjust_offset; FOR i := cols DOWNTO 1 DO BEGIN IF dx>=i THEN scroll_text(y0+1,y0+colht,x0,x0+cols*colw-1,0,colw); IF dx<=-i THEN scroll_text(y0+1,y0+colht,x0,x0+cols*colw-1,0,-colw); END; FOR i := 1 TO cols DO IF (i+dx>cols) OR (i+dx<1) THEN redraw_column(i); nr := posn_in_list(thispage) - listoffset; { wo steht der Zeiger? } thispage^.dejavu := True; listentry(thispage,nr); x := x0+colw*(nr DIV colht); y := y0+1+nr MOD colht; GotoXY(x,y); IF really THEN BEGIN IF jobcursor THEN Write(#155,'2m'); Write('>'#155'0m'); END ELSE Write(' '); END; PROCEDURE redraw_list; { aktualisiert die gesamte Seitenliste } VAR i: Integer; hilf: p_onepage; BEGIN IF adjust_offset<>0 THEN; { Wert ist egal } GotoXY(x0,y0); Write(#155'0m Im Speicher:'); lsizex := 39-Length(IntStr(listsize)); GotoXY(39-5,y0); Write(listsize:5); hilf := page_on_posn(listoffset); FOR i := 0 TO cols*colht-1 DO BEGIN listentry(hilf,i); IF hilf<>Nil THEN hilf := hilf^.next; END; mark_list(True); END; PROCEDURE redraw_rows(rows: Integer); { gibt die ersten bzw. die letzten <-rows> Zeilen der Seitenliste } { aus, nicht ganz trivial } VAR i,j: Integer; hilf: p_onepage; BEGIN hilf := page_on_posn(listoffset); FOR i := 1 TO cols DO FOR j := 1 TO colht DO BEGIN IF (j<=rows) OR (j>colht+rows) THEN listentry(hilf,(j-1)+(i-1)*colht); IF hilf<>Nil THEN hilf := hilf^.next; END; END; PROCEDURE update_list{(start: p_onepage; delta: Integer)}; { Es wurden Seiten in die Liste eingefügt (delta>0) bzw. entfernt (delta<0). } { ist die erste Seite, die sich dadurch geändert hat. } { delta=0 ist auch zulässig, z. B. um für eine aktualisierte Nummer wieder } { Fettdruck zu erzwingen. } VAR i,nr: Integer; hilf: p_onepage; BEGIN lsizex := 39-Length(IntStr(listsize)); GotoXY(39-5,y0); Write(#155'0m',listsize:5); { wo auf dem Bildschirm ist die bezeichnete Seite? } nr := posn_in_list(start) - listoffset; IF delta=0 THEN BEGIN IF nr IN [0..cols*colht-1] THEN listentry(start,nr); Exit; END; { ein paar Spalten komplett scrollen, eine nur zum Teil } FOR i := 1 TO cols DO BEGIN IF (i-1)*colht>=nr THEN scroll_text(y0+1,y0+colht,x0+(i-1)*colw,x0+i*colw-1,-delta,0) ELSE IF i*colht>=nr+Abs(delta) THEN scroll_text(y0+1+nr MOD colht,y0+colht,x0+(i-1)*colw,x0+i*colw-1,-delta,0) END; hilf := start; FOR i := 0 TO delta DO BEGIN { einer zuviel, ist aber Absicht ... } IF nr+i IN [0..cols*colht-1] THEN listentry(hilf,nr+i); IF hilf<>Nil THEN hilf := hilf^.next; END; redraw_rows(delta); { '>' neu setzten, hat evtl. sogar den Bildschirm verlassen: } mark_list(True); END; FUNCTION page_from_list{(x,y: Integer): p_onepage}; { zu einer angeklickten Zeichenposition die Seite herausfinden } VAR nr: Integer; hilf: p_onepage; BEGIN page_from_list := Nil; IF (y IN [y0+1..y0+colht]) AND (x IN [x0-2..x0+cols*colw+2]) THEN BEGIN nr := listoffset + y - (y0+1) + colht*(Round((x-x0)/colw+0.5)-1); page_from_list := page_on_posn(nr); END; END; PROCEDURE hilite_crsr; { momentane Funktion des Cursors anzeigen } BEGIN mark_list(True); mark_queue(True); END; PROCEDURE fileinfo; CONST x0=1; y0=26; VAR l,space: Integer; BEGIN GotoXY(x0,y0); Write(#155'0mDatei ('); fix1 := x0 + 7; fix2 := fix1 + 4; IF asciifile THEN BEGIN Write('ASCII, '); fix2 := fix2 + 3; END ELSE Write('VT, '); fix3 := fix2 + 11; IF overwrite THEN BEGIN Write('}berschr.): '); fix3 := fix3 + 1; END ELSE Write('anf}gend): '); space := 80 - fix3; IF withicon THEN space := space - 10; l := Length(outputname); IF numbering THEN l := l + 4; IF l>space THEN Write(#155'2m...',Copy(outputname,l-space+4,space-3)) ELSE Write(#155'2m',outputname); IF l>space THEN fix4 := fix3 + space ELSE fix4 := fix3 + l; IF numbering THEN Write('.###'); IF withicon THEN Write(#155'0m, mit Icon'); ClrEoL; END; PROCEDURE test{(active: Boolean)}; { Decodertest, sollte aus einer Schleife heraus aufgerufen werden. } { für active=false wird ein leeres Testfeld erzeugt. } CONST x0=26; y0=1; VAR stat: Byte; i: Integer; zeit: str80; ch: char; tag,min,tic: Long; PROCEDURE zweistellig(x: Integer); BEGIN Write(x DIV 10, x MOD 10); END; BEGIN GotoXY(x0,y0); Write(#155'0mStatus:'); IF NOT active THEN BEGIN FOR stat := 1 TO 5 DO BEGIN GotoXY(x0,y0+stat); Write(' '); { 13 Spaces } END; Write(#155,'2m'); END; GotoXY(x0,y0+1); Write('Bus:'); GotoXY(x0+5,y0+1); Write('AV:'); GotoXY(x0+5,y0+2); Write('VT:'); GotoXY(x0,y0+3); Write(' VT:'); GotoXY(x0,y0+4); Write('Sys:'); IF active THEN BEGIN Write(#155,'2m'); stat := VTstat; GotoXY(x0,y0+2); IF i2c_status=0 THEN Write('OK ') ELSE Write('Err',i2c_status); FOR i := 1 TO 2 DO BEGIN GotoXY(x0+9,y0+i); IF i2c_status=0 THEN IF (stat AND i)<>0 THEN Write('ja ') ELSE Write('nein') ELSE Write(' ') END; { Zeit aus dem VT-Seitenspeicher abfragen: } gettime(aktspeicher,zeit); GotoXY(x0+5,y0+3); Write(zeit); { zum Vergleich: Amiga-Zeit } telltime(tag,min,tic); GotoXY(x0+5,y0+4); zweistellig(min DIV 60); Write(':'); zweistellig(min MOD 60); Write(':'); zweistellig(tic DIV 50); END; Write(#155'0m'); END; CONST pgoffx=40; { PROCEDURE writepage() und FUNCTION number_from_page() includen: } CONST unit_bildschirm=1701; {$path "PAS:prg/vt/"; incl "dbluse.p" } PROCEDURE redraw_all; { kompletter Neuaufbau des Bildschirms, inklusive clrscr } BEGIN ClrScr; redraw_queue(-1); test(False); redraw_list; fileinfo; writepage(thispage,True); END; FUNCTION click_action{(x,y: Integer): Char}; { Ein paar bestimmte Sachen, die man anklicken kann } BEGIN click_action := ' '; IF (y=1) AND (x IN [26..32]) THEN click_action := 'T'; { "Status" } IF (y=1) AND (x IN [2..13]) THEN click_action := 'S'; { "Seitensuche" } IF (y=7) AND (x IN [2..6]) THEN click_action := 'J'; { "Jobs" } IF (y=7) AND (x IN [10..22]) THEN click_action := 'L'; { "Im Speicher" } IF (y=7) AND (x IN [lsizex..38]) THEN click_action := 'K'; { Löschen } IF (y=26) THEN BEGIN IF x IN [1..fix1-3] THEN click_action := 'D'; { Dateiname } IF x IN [fix1..fix2-3] THEN click_action := 'F'; { Format } IF x IN [fix2..fix3-4] THEN click_action := 'M'; { Modus } IF x IN [fix3..fix4-1] THEN click_action := 'N'; { Numerierung } IF x IN [fix4..80] THEN click_action := 'I'; { Icon? } END; IF (x>=40) THEN CASE y OF 1..8: click_action := '-'; { oberes Seitendrittel } 9..16: click_action := '0'; { Seitenmitte } 17..24: click_action := '+'; { unteres Seitendrittel } OTHERWISE; END; END; BEGIN { Initialisierungsteil } listoffset := 0; jobcursor := False; incomplete := False; concealed := True; queue_input := ''; END.