home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------ *)
- (* WINDOW.PAS *)
- (* *)
- (* (c) 1988 by Christian Steingräber und TOOLBOX *)
- (* ------------------------------------------------------ *)
- UNIT window;
-
- INTERFACE
-
- USES Crt, Dos;
-
- CONST
- opened = TRUE; { Flipmenü schon geöffnet }
- not_opened = FALSE; { Flipmenü noch nicht geöffnet }
- ver = TRUE; { vertikales Flipmenü }
- hor = FALSE; { horizontales Flipmenü }
-
- VAR { Farben für FlipMenue }
- FmTxtColor, { Textfarbe }
- FmBckColor, { Texthintergrund }
- FmFrmColor, { Rahmenfarbe }
- FmBrdColor: BYTE; { Rahmenhintergrund }
- MenueHelp, { Menühilfe erlaubt? }
- MenueMove: BOOLEAN; { Menüverschiebung erlaubt? }
-
- PROCEDURE MkWindow(x1, y1, x2, y2, Style, TxtColor,
- BckColor, BrdColor: BYTE);
-
- PROCEDURE MkMidWindow(Breite, Laenge, Style, TxtColor,
- BckColor, BrdColor: BYTE);
- (* Öffnet ein Fenster mittig ausgerichtet *)
-
- PROCEDURE RmWindow; (* Schließt das aktuelle Fenster.*)
-
- PROCEDURE MvWindow(x_dif, y_dif: INTEGER);
- (* Verschiebt das aktuelle Fenster. Positive Werte bewirken
- eine Verschiebung nach rechts bzw. unten, negative Werte
- nach links bzw. oben. *)
-
- PROCEDURE SetHeader(Header: STRING);
- (* Setzt den übergebenen String als Überschrift in die Mitte
- der oberen Rahmenkante des aktuellen Fensters. *)
-
- PROCEDURE SetFoot(Foot: STRING);
- (* Setzt den übergebenen String als Fußnote in die rechte
- Ecke der unteren Rahmenkante des aktuellen Fensters. *)
-
- FUNCTION FlipMenue(VAR x, y: BYTE;
- str: STRING; _ver: BOOLEAN;
- VAR _opened : BOOLEAN;
- VAR Position: BYTE): INTEGER;
-
- IMPLEMENTATION
-
- CONST
- monoscreen : WORD = $b000; (* Herkules-Segmentadresse *)
- colorscreen: WORD = $b800; (* CGA-Segmentadresse *)
- monochrom = 7;
- maxwin = 10;
-
- TYPE
- t_str80 = STRING[80];
- scrinhalt = ARRAY [0..3999] OF BYTE;
- wintyp = RECORD
- x1, y1, x2, y2: BYTE;
- END;
- screens = RECORD
- bild : scrinhalt;
- dim : wintyp;
- x, y : BYTE;
- shape: INTEGER;
- END;
-
- VAR
- win: RECORD
- dim: wintyp;
- tiefe: BYTE;
- keller: ARRAY [1..maxwin] OF ^screens;
- END;
- monobuffer : scrinhalt ABSOLUTE $b000:$0000;
- colorbuffer: scrinhalt ABSOLUTE $b800:$0000;
- screenmode : BYTE ABSOLUTE $0040:$0049;
- aktive_page: BYTE ABSOLUTE $0040:$0062;
- videobuffer: WORD;
-
- PROCEDURE off_cursor; { Cursor unsichtbar }
- VAR
- regs: registers;
- BEGIN
- WITH regs DO BEGIN
- ah:=2; bh:= aktive_page; dx:=$34A1;
- END;
- INTR($10, regs);
- END;
-
- PROCEDURE where_cursor(VAR x, y:BYTE);
- VAR
- crt_pages: ARRAY [0..7] OF INTEGER ABSOLUTE $40:$50;
- BEGIN
- x := lo(crt_pages[aktive_page])+1;
- y := hi(crt_pages[aktive_page])+1;
- END;
-
- PROCEDURE set_cursor(x, y:BYTE);
- VAR
- regs: registers;
- BEGIN
- WITH regs DO BEGIN
- ah:= 2; bh:= aktive_page;
- dh:= y - 1; dl:= x - 1;
- END;
- INTR($10, regs);
- END;
-
- PROCEDURE initwindow;
- BEGIN
- IF screenmode = monochrom THEN videobuffer := monoscreen
- ELSE videobuffer := colorscreen;
- WITH win.dim DO BEGIN
- x1 := 1; y1 := 1;
- x2 := 80; y2 := 25;
- END;
- win.tiefe := 0;
- MenueHelp := TRUE;
- MenueMove := TRUE;
- FmTxtColor:= lightgray;
- FmBckColor:= black;
- FmBrdColor:= black;
- FmFrmColor:= white;
- END;
-
- PROCEDURE winframe(x1, y1, x2, y2, Style,
- TxtColor, BckColor: BYTE);
- VAR
- ver, hor, elo, ero, elu, eru, attribut : BYTE;
- i, j, k, l : WORD;
- BEGIN
- CASE Style OF
- 1: BEGIN (* einfache Linie *)
- ver:= 196; hor:= 179; elo:= 218;
- ero:= 191; elu:= 192; eru:= 217;
- END;
- 2: BEGIN (* doppelte Linie *)
- ver:= 205; hor:= 186; elo:= 201;
- ero:= 187; elu:= 200; eru:= 188;
- END;
- ELSE BEGIN
- ver:= Style; hor:= Style; elo:= Style;
- ero:= Style; elu:= Style; eru:= Style;
- END;
- END;
- attribut := BckColor SHL 4 + TxtColor;
- j := (y1-1)*160;
- MEMW[videobuffer:j+(x1-1)*2] := attribut SHL 8 + elo;
- k := attribut SHL 8 + ver;
- FOR i := x1 TO x2-2 DO memw[videobuffer:j+i*2] := k;
- MEMW[videobuffer:j+(x2-1)*2] := attribut SHL 8 + ero;
- j := (x1-1)*2;
- k := (x2-1)*2;
- l := attribut SHL 8 + hor;
- FOR i := y1 TO y2-2 DO BEGIN
- MEMW[videobuffer:i*160+j] := l;
- MEMW[videobuffer:i*160+k] := l;
- END;
- j := (y2-1)*160;
- MEMW[videobuffer:j+(x1-1)*2] := attribut SHL 8 + elu;
- k := attribut SHL 8 + ver;
- FOR i := x1 TO x2-2 DO MEMW[videobuffer:j+i*2] := k;
- MEMW[videobuffer:j+(x2-1)*2] := attribut SHL 8 + eru;
- crt.window(x1+1, y1+1, x2-1, y2-1);
- END;
-
- PROCEDURE MkWindow;
- VAR
- regs: registers;
- BEGIN
- WITH win DO BEGIN
- tiefe := tiefe + 1;
- IF (tiefe > maxwin) OR (maxavail < 4008) THEN BEGIN
- crt.window(1,1,80,25);
- WriteLn(#7,' Fehler: Zu viele Fenster offen! ');
- HALT;
- END;
- new(keller[tiefe]); (* Speicher auf Heap erstellen *)
- IF screenmode = monochrom THEN
- keller[tiefe]^.bild := monobuffer
- ELSE
- keller[tiefe]^.bild := colorbuffer;
- keller[tiefe]^.dim := dim; { Fenstergröße retten }
- where_cursor(keller[win.tiefe]^.x, { Cursorposition }
- keller[win.tiefe]^.y); { retten }
- regs.ah := 3; { Cursorform retten }
- INTR($10,regs);
- keller[win.tiefe]^.shape := regs.cx;
- END;
- winframe(x1, y1, x2, y2, Style, TxtColor, BrdColor);
- textcolor(TxtColor);
- textbackground(BckColor);
- ClrScr;
- win.dim.x1 := x1+ 1; win.dim.x2 := x2- 1;
- win.dim.y1 := y1+ 1; win.dim.y2 := y2- 1;
- END;
-
- PROCEDURE MkMidWindow;
- BEGIN
- MkWindow((80 - Breite) SHR 1, (25 - Laenge) SHR 1,
- (80 - Breite) SHR 1 + Breite + 1,
- (25 - Laenge) SHR 1 + Laenge + 1,
- Style, TxtColor, BckColor, BrdColor);
- END;
-
- PROCEDURE SetHeader;
- VAR
- x, y: BYTE;
- BEGIN
- where_cursor(x, y);
- WITH win DO
- IF tiefe <> 0 THEN
- WITH dim DO BEGIN
- crt.window(1,1,80,25);
- GotoXY(x1+(x2-x1+1-length(Header)) SHR 1, y1-1);
- Write(Header);
- crt.window(x1, y1, x2, y2);
- END;
- set_cursor(x, y);
- END;
-
- PROCEDURE SetFoot;
- VAR
- x, y: BYTE;
- BEGIN
- where_cursor(x, y);
- WITH win DO
- IF tiefe <> 0 THEN
- WITH dim DO BEGIN
- crt.window(1,1,80,25);
- GotoXY(x2 + 1 - length(Foot), y2+ 1);
- Write(Foot);
- crt.window(x1, y1, x2, y2);
- END;
- set_cursor(x, y);
- END;
-
- PROCEDURE RmWindow;
- VAR
- act_color, x, y : BYTE;
- regs : registers;
- BEGIN
- WITH win DO BEGIN
- IF screenmode = monochrom THEN
- monobuffer := keller[tiefe]^.bild
- ELSE
- colorbuffer := keller[tiefe]^.bild;
- dispose(keller[tiefe]); { Heap freigeben }
- dim := keller[tiefe]^.dim;
- crt.window(dim.x1, dim.y1, dim.x2, dim.y2);
- set_cursor(keller[tiefe]^.x, keller[tiefe]^.y);
- regs.ah := 1;
- regs.cx := keller[tiefe]^.shape;
- INTR($10,regs);
- where_cursor(x, y);
- act_color := Mem[videobuffer:(y-1)*160+(x-1)*2];
- TextColor(act_color AND $0f);
- TextBackground(act_color SHR 4);
- tiefe := tiefe - 1;
- END;
- END;
-
- PROCEDURE hilfe; { Hilfsfenster für FlipMenue }
- VAR
- ch: CHAR;
- BEGIN
- IF MenueHelp THEN BEGIN
- MkMidWindow(60, 16, 1, 15, 0, 0);
- SetHeader(' Menü - Hilfe ');
- WriteLn;
- TextColor(0); TextBackground(7);
- WriteLn(' Wenn Scroll-Lock aktiv ist, ');
- TextColor(7); TextBackground(0);
- WriteLn(' - blinken die Ecken des Menü-Fensters,');
- WriteLn(' - kann das Fenster mit den Pfeiltasten ver'+
- 'schoben werden,');
- WriteLn(' - kann mit der Control-Taste die seitliche '+
- 'Verschiebung');
- WriteLn(' beschleunigt werden,');
- WriteLn(' - erreichen Sie über F1 diese Hilfe.');
- WriteLn;
- TextColor(0); TextBackground(7);
- WriteLn(' Wenn Scroll-Lock nicht aktiv ist, ');
- TextColor(7); TextBackground(0);
- WriteLn(' - kann mit den Pfeiltasten der Inverse Bal'+
- 'ken ver-');
- WriteLn(' schoben werden,');
- WriteLn(' - kann mit Return (''Enter'') der Menüpunkt'+
- ', auf dem');
- WriteLn(' der Balken steht, gewählt werden,');
- WriteLn(' - kann jeder Menüpunkt durch Drücken sei'+
- 'nes hellen');
- WriteLn(' Buchstabens gewählt werden.');
- TextColor(15);
- SetFoot(' Weiter mit ESC...');
- off_cursor;
- REPEAT
- ch:= ReadKey;
- UNTIL ch = #27;
- RmWindow;
- END;
- END;
-
- FUNCTION scrollock: BOOLEAN; { Auf Scroll-Lock testen }
- VAR regs: registers;
- BEGIN
- regs.ah := $02; INTR($16,regs);
- scrollock := regs.al AND $10 <> 0;
- END;
-
- PROCEDURE MvWindow;
- VAR
- buffer : scrinhalt;
- old_x, old_y,
- anzahl, i,
- sp1, sp2 : BYTE;
- BEGIN
- where_cursor(old_x, old_y);
- WITH win DO BEGIN
- IF screenmode = monochrom THEN BEGIN
- buffer := monobuffer;
- monobuffer := keller[tiefe]^.bild;
- END ELSE BEGIN
- buffer := colorbuffer;
- colorbuffer:= keller[tiefe]^.bild;
- END;
- sp1 := (dim.x1- 2)* 2; { linke Fenster-Spalte }
- sp2 := (dim.x1+ x_dif- 2)* 2; { rechte Fenster-Spalte }
- anzahl:= (dim.x2- dim.x1+ 3)*2; { Bytes einer Zeile }
- FOR i := dim.y1-1 TO dim.y2+1 DO
- move(buffer[(i-1)*160 + sp1],
- mem[videobuffer:(i+y_dif-1)*160 + sp2], anzahl);
- dim.x1 := dim.x1+ x_dif; dim.x2 := dim.x2+ x_dif;
- dim.y1 := dim.y1+ y_dif; dim.y2 := dim.y2+ y_dif;
- crt.window(dim.x1, dim.y1, dim.x2, dim.y2);
- END;
- set_cursor(old_x+x_dif,old_y+y_dif);
- END;
-
- PROCEDURE movewindow; { FlipMenue bewegen }
- VAR
- ch : CHAR;
- i, j, k: INTEGER;
- tcolor : BYTE;
- Foot : ARRAY [1..140] OF BYTE;
-
- PROCEDURE warnung;
- BEGIN
- MkMidWindow(38, 1, 2, 15, 0, 0);
- SetHeader(' Achtung ');
- TextColor(7);
- Write(' Bitte erst Scroll-Lock deaktivieren!');
- TextColor(15);
- SetFoot(' Weiter ohne Scroll-Lock ');
- off_cursor;
- REPEAT UNTIL NOT scrollock;
- RmWindow;
- END;
-
- BEGIN
- WITH win.dim DO BEGIN { blinkende Ecken }
- tcolor := Mem[videobuffer:(y1-1)*160+(x1-1)*2+1]
- OR 128;
- j := (x1-2)*2+1;
- k := x2*2+1;
- Mem[videobuffer:(y1-2)*160+j] := tcolor;
- Mem[videobuffer:(y1-2)*160+k] := tcolor;
- Mem[videobuffer:(y2)*160+j] := tcolor;
- Mem[videobuffer:(y2)*160+k] := tcolor;
- IF MenueHelp THEN BEGIN
- Move(Mem[videobuffer:y2*160+(x1-1)*2], Foot[1],
- (x2-x1+1)*2);
- TextColor(15);
- IF x2 - x1 > 8 THEN SetFoot('F1 = Hilfe')
- ELSE IF x2 - x1 > 0 THEN SetFoot('F1')
- END;
- END;
- WHILE scrollock DO
- IF KeyPressed THEN BEGIN
- ch := ReadKey;
- IF (ch = #0) AND KeyPressed THEN BEGIN
- ch := ReadKey;
- WITH win.dim DO
- CASE ch OF
- #75: IF(x1 > 2) THEN MvWindow(-1,0);
- #115: IF(x1>3) THEN MvWindow(-2,0);
- #77: IF(x2 < 79) THEN MvWindow(1,0);
- #116: IF(x2 < 78) THEN MvWindow(2,0);
- #72: IF(y1 > 2) THEN MvWindow(0,-1);
- #80: IF(y2 < 24) THEN MvWindow(0,1);
- #59: hilfe;
- ELSE warnung;
- END
- END ELSE warnung;
- END;
- tcolor := tcolor AND 127;
- WITH win.dim DO BEGIN
- j := (x1-2)*2+1;
- k := x2*2+1;
- Mem[videobuffer:(y1-2)*160+j] := tcolor;
- Mem[videobuffer:(y1-2)*160+k] := tcolor;
- Mem[videobuffer:(y2)*160+j] := tcolor;
- Mem[videobuffer:(y2)*160+k] := tcolor;
- IF MenueHelp THEN
- Move(Foot[1], Mem[videobuffer:y2*160+(x1-1)*2],
- (x2-x1+1)*2);
- END;
- END;
-
- FUNCTION FlipMenue;
- VAR
- i, Breite, ausgewaehlt, anzahl : INTEGER;
- auswahl : ARRAY [1..24] OF STRING[70];
- Foot, Header, leerstr : STRING[70];
- hotkeys : STRING[24];
- hkcolor : BYTE;
- kontrolle, antwort : CHAR;
- no_mark, hotkey : BOOLEAN;
-
- PROCEDURE inv; { ausgewählten Menüpunkt invertieren }
- BEGIN
- i := Pos('#', auswahl[ausgewaehlt]);
- IF _ver THEN GotoXY(2, ausgewaehlt)
- ELSE GotoXY((ausgewaehlt - 1) * Breite + 2, 1);
- TextColor(FmBckColor);
- TextBackground(FmTxtColor AND 7);
- Write(Copy(auswahl[ausgewaehlt], 1, i- 1));
- Write(Copy(auswahl[ausgewaehlt], i+ 1, 70));
- off_cursor;
- END;
-
- PROCEDURE norm; { Inverser Menüpunkt wieder normal }
- BEGIN
- i := Pos('#', auswahl[ausgewaehlt]);
- IF i = 0 THEN i := 71;
- TextBackground(FmBckColor);
- TextColor(FmTxtColor);
- IF _ver THEN GotoXY(2, ausgewaehlt)
- ELSE GotoXY((ausgewaehlt - 1) * Breite + 2, 1);
- Write(Copy(auswahl[ausgewaehlt], 1, i- 1));
- IF i < 71 THEN BEGIN
- TextColor(hkcolor);
- Write(Copy(auswahl[ausgewaehlt], i+ 1, 1));
- TextColor(FmTxtColor);
- END;
- Write(Copy(auswahl[ausgewaehlt], i+ 2, 70));
- off_cursor;
- END;
-
- BEGIN
- Breite := 1; anzahl := 1;
- hotkeys:= ''; Header := ''; Foot := '';
- no_mark:= TRUE;
- { Menüpunkte, Überschrift und Fußnote holen }
- WHILE Pos('_', Str) <> 0 DO BEGIN
- auswahl[anzahl] := Copy(Str, 1, Pos('_', Str)- 1);
- Delete(Str, 1, Pos('_', Str));
- IF Length(auswahl[anzahl]) > Breite THEN BEGIN
- Breite:= Length(auswahl[anzahl]);
- IF (Copy(auswahl[anzahl], 1, 1) <> '(') AND
- (Copy(auswahl[anzahl], 1, 1) <> ')') AND
- (Pos('#', auswahl[anzahl]) = 0) THEN
- Breite := Succ(Breite);
- END;
- CASE Ord(auswahl[anzahl][1]) OF
- 40 {'('}: Header := Copy(auswahl[anzahl],2,70);
- 41 {')'}: Foot := Copy(auswahl[anzahl],2,70);
- ELSE BEGIN
- IF Pos('#', auswahl[anzahl]) <> 0 THEN BEGIN
- no_mark := FALSE;
- hotkeys := hotkeys + Copy(auswahl[anzahl],
- Pos('#', auswahl[anzahl])+ 1, 1);
- END ELSE
- hotkeys := hotkeys + #0;
- anzahl := Succ(anzahl);
- END;
- END;
- END;
- anzahl := Pred(anzahl);
- { Breite für horizontales Menü berechnen }
- IF not _ver THEN BEGIN
- Breite := 1; no_mark:= TRUE;
- FOR ausgewaehlt := 1 TO anzahl DO BEGIN
- IF Length(auswahl[ausgewaehlt]) > Breite THEN BEGIN
- Breite := Length(auswahl[ausgewaehlt]);
- IF Pos('#', auswahl[ausgewaehlt]) <> 0 THEN
- no_mark := FALSE;
- END;
- END;
- END;
- Breite := Breite + 1;
- IF no_mark THEN Breite := Breite + 1;
- IF (FmTxtColor and 8) = 8 THEN
- hkcolor := FmTxtColor AND 7
- ELSE
- hkcolor := FmTxtColor OR 8;
- (* alle Menüpunkte auf die gleiche Länge *)
- FillChar(leerstr, Succ(Breite), ' ');
- FillChar(leerstr, 1, Chr(Breite));
- FOR ausgewaehlt := 1 TO anzahl DO BEGIN
- hotkeys[ausgewaehlt] := Upcase(hotkeys[ausgewaehlt]);
- IF Pos('#', auswahl[ausgewaehlt]) = 0 THEN i := 1
- ELSE i := 0;
- IF length(auswahl[ausgewaehlt]) < Breite THEN
- auswahl[ausgewaehlt] := auswahl[ausgewaehlt]+
- Copy(leerstr, 1, Breite-
- Length(auswahl[ausgewaehlt])-
- 1- i);
- END;
- IF not _opened THEN BEGIN
- IF x = 0 THEN
- IF _ver THEN x := (80 - Breite - 2) SHR 1
- ELSE x := (80 - Breite * anzahl - 2) SHR 1;
- IF y = 0 THEN
- IF _ver THEN y := (25 - anzahl - 2) SHR 1
- ELSE y := 12;
- IF _ver THEN
- MkWindow(x, y, x + Breite + 1, y + anzahl + 1, 2,
- FmFrmColor, FmBckColor, FmBrdColor)
- ELSE MkWindow(x, y, x + Breite * anzahl + 1, y + 2, 2,
- FmFrmColor, FmBckColor, FmBrdColor);
- _opened := TRUE;
- TextColor(FmTxtColor);
- TextBackground(FmBckColor);
- FOR ausgewaehlt := 1 TO anzahl DO norm;
- TextColor(FmFrmColor); TextBackground(FmBrdColor);
- SetHeader(Header);
- SetFoot(Foot);
- END;
- ausgewaehlt := Position;
- IF (ausgewaehlt > anzahl) OR (ausgewaehlt < 1) THEN
- ausgewaehlt := 1;
- inv;
- antwort := #0;
- hotkey := FALSE;
- REPEAT
- IF (scrollock AND MenueMove) THEN movewindow;
- IF KeyPressed THEN BEGIN
- antwort := ReadKey;
- norm;
- IF antwort = #0 THEN BEGIN
- IF KeyPressed THEN BEGIN
- kontrolle := ReadKey;
- CASE kontrolle OF
- #80, #77: IF ausgewaehlt < anzahl THEN
- ausgewaehlt := SUCC(ausgewaehlt)
- ELSE ausgewaehlt := 1;
- #72, #75: IF ausgewaehlt > 1 THEN
- ausgewaehlt := PRED(ausgewaehlt)
- ELSE ausgewaehlt:= anzahl;
- #71: ausgewaehlt := 1;
- #79: ausgewaehlt := anzahl;
- ELSE BEGIN
- antwort := kontrolle;
- hotkey := TRUE;
- END;
- END;
- END;
- END ELSE BEGIN
- i := Pos(Upcase(antwort), hotkeys);
- IF i <> 0 THEN BEGIN
- antwort := #13;
- ausgewaehlt := i;
- END;
- IF antwort = #27 THEN hotkey := TRUE;
- END;
- inv;
- END;
- UNTIL (antwort = #13) OR (hotkey = TRUE);
- norm;
- Position := ausgewaehlt;
- IF antwort <> #13 THEN ausgewaehlt := Ord(antwort)* -1;
- FlipMenue := ausgewaehlt;
- x := win.dim.x1 - 1;
- y := win.dim.y1 - 1;
- GotoXY(1, 1);
- END;
-
-
- BEGIN
- initwindow;
- END.
-
- (* ------------------------------------------------------ *)
- (* Ende von WINDOW.PAS *)