home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------ *)
- (* ZOOMER.PAS *)
- (* Speicherresidente Zeichenlupe für Turbo Pascal 5.5 *)
- (* (c) 1990 Gerd Arnold & TOOLBOX *)
- (* ------------------------------------------------------ *)
-
- {$B-,D-,F-,I-,O-,R-,S-,V-} { alle Prüfungen aus }
- {$M 1024,0,655360} { wenig Stack, Heap durch TSR begrenzt }
-
- PROGRAM Zoomer;
-
- USES TSR, Crt, DOS;
-
- CONST
- WinMaxHoehe = 10; { Höhe des Fensters }
- TYPE
- ZeichenTyp = ARRAY[0..7] OF BYTE; { 8x8-Zeichen }
- FensterType = ARRAY[1..WinMaxHoehe, 1..80] OF WORD;
- ScreenType = ARRAY[1..25, 1..80] OF WORD;
- CHARSET = SET OF CHAR;
- CONST
- ZoomID = 11; { Kennziffer }
- Programm = 'ZOOMER 1.1'; { Programmname }
- Hotkey = $6800; { Aktivierung: Alt-F1 }
- HotkeyName = 'Alt-F1';
- MaxPosition = 6; { Anzahl Windowpositionen }
- LetterBreite = 9; { bestimmt Größe der Lücke }
- Rechts : BYTE = 80; { rechter Rand }
- Unten : BYTE = 25; { unterer Rand }
- AnzLetter : BYTE = 5; { Buchstaben im Fenster }
- Position : BYTE = 1; { Fensterposition }
- Lesbar : CHARSET = { Lesbare Zeichen }
- [#48..#57, #65..#90, #97..#122, #128..#165, #128..#165];
- VAR
- WinX1, WinX2, WinY1, WinY2, CurX, CurY, CurXAlt, CurYAlt,
- WinBreite : BYTE; { Breite des Fensters }
- Fenster : FensterType;
- Screen : ^ScreenType; { Pointer auf Grafiksp.}
- Passage, Begriff : STRING[10]; { Suchbegriff }
- DrawNeu, Abbruch : BOOLEAN; { Flag: neu zeichnen? }
- NormAttr, FindAttr : BYTE; { Attribute für Window }
- CONST
- Zeichen: ARRAY[0..255] OF ZeichenTyp =
- { Hier wird der mit Hilfe von "MAKECHAR.PAS" erzeugte 8x8-
- Zeichensatz aus der Datei "ZSATZ.INC" eingebunden! }
- {$I ZSATZ.INC}
-
- PROCEDURE Pieps; { Pieps! }
- BEGIN
- Sound(800); Delay(100); NoSound;
- END;
-
- PROCEDURE GetMode; { Adresse Bildschirmspeicher ermitteln }
- VAR R : Registers;
- BEGIN
- R.AH := $0F; Intr($10, R);
- IF NOT (R.AL IN [2, 3, 7]) THEN BEGIN { 80x25-Textmodus? }
- Pieps; Abbruch := TRUE; { Nein! }
- Exit; { Abbruch... }
- END;
- IF (MEM[0000:1040] AND 48) <> 48 THEN BEGIN
- Screen := Ptr ($B800, $0000); { Farbgrafik }
- NormAttr := White OR BLACK SHL 4;
- FindAttr := LightGreen OR BLACK SHL 4;
- END ELSE BEGIN
- Screen := Ptr ($B000, $0000); { Hercules }
- NormAttr := 7;
- FindAttr := 15;
- END;
- END;
-
- PROCEDURE WriteAt(x, y : BYTE; ch : CHAR; Attr : BYTE);
- { schreibt ein Zeichen direkt in den Bildschirmspeicher }
- BEGIN
- Screen^[y, x] := WORD(Ord(ch) OR (Attr SHL 8));
- END;
-
- FUNCTION UpChar(ch : CHAR) : CHAR; { verbessertes "UpCase" }
- BEGIN
- CASE ch OF
- 'ä' : UpChar := 'Ä'; { deutsche Umlaute }
- 'ö' : UpChar := 'Ö'; { berücksichtigen }
- 'ü' : UpChar := 'Ü';
- ELSE UpChar := UpCase(ch); END;
- END;
-
- PROCEDURE GetPosition(VAR x, y : BYTE);
- BEGIN { Position für Window ermitteln }
- CASE Position OF
- 1: BEGIN
- x := 1; y := 1;
- END;
- 2: BEGIN
- x := 1; y := (Unten - WinMaxHoehe) DIV 2 + 1;
- END;
- 3: BEGIN
- x := 1; y := Unten - WinMaxHoehe + 1;
- END;
- 4: BEGIN
- x := Rechts - AnzLetter * LetterBreite - 2; y := 1;
- END;
- 5: BEGIN
- x := Rechts - AnzLetter * LetterBreite - 2;
- y := (Unten - WinMaxHoehe) DIV 2 + 1;
- END;
- 6: BEGIN
- x := Rechts - AnzLetter * LetterBreite - 2;
- y := Unten - WinMaxHoehe + 1;
- END;
- END;
- END;
-
- PROCEDURE MakeWindow(Attr : BYTE); { Fenster erzeugen }
- VAR x, y : BYTE;
- CONST
- EckLO = #201; EckRO = #187; { Blockgrafikzeichen }
- EckLU = #200; EckRU = #188; { für doppelten }
- Horiz = #205; Vert = #186; { Rahmen um Window }
- BEGIN
- Dec(Position);
- REPEAT { gültige Position für Window ermitteln }
- Inc(Position);
- IF Position > MaxPosition THEN Position := 1;
- GetPosition(WinX1, WinY1);
- WinX2 := WinX1 + 2 + LetterBreite * AnzLetter;
- WinY2 := WinY1 + WinMaxHoehe - 1;
- WinBreite := (WinX2 - WinX1 + 1) * 2;
- UNTIL NOT (CurY IN [WinY1..WinY2]);
- FOR y := WinY1 TO WinY2 DO BEGIN { Hintergrund sichern }
- Move(Screen^ [y, WinX1],
- Fenster[y - WinY1+1] , WinBreite);
- FillChar(SCREEN^ [y, WinX1], WinBreite, 0); { löschen }
- END;
- FOR x:=Succ(WinX1) TO Pred(WinX2) DO BEGIN
- WriteAt(x, WinY1, Horiz, Attr); { Rahmen zeichnen }
- WriteAt(x, WinY2, Horiz, Attr);
- END;
- FOR x:=Succ(WinY1) TO Pred(WinY2) DO BEGIN
- WriteAt(WinX1, x, Vert, Attr);
- WriteAt(WinX2, x, Vert, Attr);
- END;
- WriteAt(WinX1, WinY1, EckLO, Attr);
- WriteAt(WinX2, WinY1, EckRO, Attr);
- WriteAt(WinX1, WinY2, EckLU, Attr);
- WriteAt(WinX2, WinY2, EckRU, Attr);
- END;
-
- PROCEDURE RestoreWindow; { Hintergrund restaurieren }
- VAR y : BYTE;
- BEGIN
- FOR y := WinY1 TO WinY2 DO
- Move(Fenster[y - WinY1 + 1],
- Screen^ [y, WinX1], WinBreite);
- END;
-
- FUNCTION GetChar(x, y : BYTE) : CHAR;
- BEGIN { Zeichen vom Bildschirm einlesen }
- IF x <= Rechts THEN GetChar := CHAR(Screen^[y, x])
- ELSE GetChar := #32;
- END;
-
- PROCEDURE WriteLetter(Letter: CHAR; Posi, Attr: BYTE);
- VAR { Vergrößertes Zeichen anzeigen }
- ASCII, xPos, x, y : BYTE;
- CONST
- Bits: ARRAY[0..7] OF BYTE = (128, 64, 32, 16, 8, 4, 2, 1);
- Voll = #219; Leer = #32;
- BEGIN
- ASCII := Ord(Letter);
- xPos := WinX1 + 2 + (Posi - 1) * LetterBreite;
- FOR y := 0 TO 7 DO BEGIN
- FOR x := 0 TO 7 DO
- IF Zeichen[ASCII, y] AND Bits[x] > 0 THEN
- WriteAt(xPos + x, Succ(WinY1 + y), Voll, Attr)
- ELSE
- WriteAt(xPos + x, Succ(WinY1 + y), Leer, Attr);
- END;
- END;
-
- PROCEDURE ShowBlock;
- VAR n : BYTE; { vergrößerten Block invers darstellen }
- BEGIN
- FOR n := 0 TO AnzLetter - 1 DO
- IF CurX + n <= Rechts THEN
- Screen^[CurY, CurX + n] :=
- Screen^[CurY, CurX + n] XOR $7F00;
- END;
-
- PROCEDURE FindWord; { sucht Zeichenfolge auf dem Monitor }
- VAR x, y, n, Match, MatchStart, Durchlauf : BYTE;
- BEGIN
- IF Length(Begriff) = 0 THEN BEGIN Pieps; Exit; END;
- x := CurX; y := CurY; n := 1; Durchlauf := 0;
- Match := 0; RestoreWindow; DrawNeu := TRUE;
- REPEAT
- Inc(x);
- IF x > Succ(Rechts - Length(Begriff) + Match) THEN BEGIN
- x := 1; Inc(y);
- IF y > Unten THEN BEGIN
- y := 1; Inc(Durchlauf); { Endlosschleife bei }
- IF Durchlauf > 1 THEN BEGIN { erfolgloser Suche }
- MakeWindow(NormAttr); { verhindern! }
- Pieps; Exit;
- END;
- END;
- END;
- IF UpChar(GetChar(x, y)) =
- UpChar(Begriff[Match+1]) THEN BEGIN
- IF Match = 0 THEN MatchStart := x;
- Inc(Match);
- END ELSE Match := 0;
- UNTIL Match = Length(Begriff);
- CurX := MatchStart; { Suche erfolgreich beenden }
- CurY := y;
- MakeWindow(NormAttr);
- END;
-
- PROCEDURE Find; { Suchwort eingeben }
- VAR
- n : BYTE;
- ch, ch2 : CHAR;
- BEGIN
- RestoreWindow; MakeWindow(FindAttr);
- DrawNeu := TRUE; n := 1; Begriff := '';
- REPEAT
- ch := ReadKey;
- IF ch = #0 THEN ch2 := ReadKey;
- IF ch = #8 THEN BEGIN { <BackSpace> }
- ch := #0;
- IF n > 1 THEN BEGIN
- Dec(n); Begriff[n] := #32;
- WriteLetter(#32, n, FindAttr);
- END;
- END;
- IF (n <= AnzLetter) AND
- NOT (ch IN [#0, #10, #13, #27]) THEN BEGIN
- Begriff[n] := ch;
- WriteLetter(ch, n, FindAttr); Inc(n);
- END;
- UNTIL ch IN [#13, #27];
- Dec(n); Begriff[0] := Chr(n);
- IF (n = 0) OR (ch = #27) THEN BEGIN { <Escape> }
- RestoreWindow; MakeWindow(NormAttr); Exit;
- END;
- FindWord;
- END;
-
- PROCEDURE FindNextChar(Step : SHORTINT);
- { sucht das nächste lesbare Zeichen auf dem Bildschirm }
- VAR x, y : BYTE;
- BEGIN
- x := CurX; y := CurY;
- REPEAT
- Inc(x, Step);
- CASE Step OF
- -1: IF x < 1 THEN BEGIN
- x := Rechts; Dec(y);
- END;
- 1: IF x > Rechts THEN BEGIN
- x := 1; Inc(y);
- END;
- END;
- IF (y < 1) OR (y > Unten) THEN Exit;
- UNTIL GetChar(x, y) IN Lesbar;
- CurX := x; CurY := y;
- END;
-
- {$F+}
- PROCEDURE Zoom; { Hauptprozedur }
- VAR
- Letter, ch, ch2 : CHAR;
- n, x, y : BYTE;
- CONST
- BigStep = 4; { Zeilensprung für <PgUp> und <PgDn> }
- BEGIN
- Passage[0] := Chr(AnzLetter); Abbruch := FALSE;
- GetMode; { Programm darf nur im 80x25- }
- IF NOT Abbruch THEN BEGIN { Modus akitviert werden ! }
- CurX := WhereX; CurY := WhereY;
- CurXAlt := WhereX; CurYAlt := WhereY;
- Begriff := '';
- MakeWindow(NormAttr);
- FOR n := 1 TO AnzLetter DO Passage[n] := ' ';
- DrawNeu := FALSE;
- REPEAT
- GotoXY(CurX, CurY); ShowBlock;
- REPEAT
- FOR n := 0 TO AnzLetter - 1 DO BEGIN
- Letter := GetChar(CurX + n, CurY);
- IF (Letter <> Passage[n+1]) OR DrawNeu THEN BEGIN
- Passage[n + 1] := Letter;
- WriteLetter(Letter, n + 1, NormAttr);
- END;
- END;
- DrawNeu := FALSE;
- UNTIL KeyPressed;
- ch := ReadKey;
- ShowBlock;
- CASE UpCase(ch) OF
- #0: BEGIN
- ch2:=ReadKey;
- CASE ch2 OF
- #72: IF CurY > 1 THEN { <hoch> }
- Dec(CurY);
- #80: IF CurY < Unten THEN { <runter> }
- Inc(CurY);
- #75: IF CurX > 1 THEN { <links> }
- Dec(CurX)
- ELSE BEGIN
- CurX := Rechts;
- IF CurY > 1 THEN
- Dec(CurY);
- END;
- #77: IF CurX < Rechts THEN { <rechts> }
- Inc(CurX)
- ELSE BEGIN
- CurX := 1;
- IF CurY < Unten THEN
- Inc(CurY);
- END;
- #115: FindNextChar(-1); { <Ctrl>-<links> }
- #116: FindNextChar(1); { <Ctrl>-<rechts> }
- #71: CurX := 1; { <Home> }
- #79: CurX := Rechts-AnzLetter+1; { <End> }
- #119: BEGIN { <Ctrl>-<Home> }
- CurX := 1; CurY := 1;
- END;
- #117: BEGIN { <Ctrl>-<End> }
- CurX := Rechts - AnzLetter + 1;
- CurY := Unten;
- END;
- #73: IF CurY > BigStep THEN { <PgUp> }
- Dec(CurY, BigStep)
- ELSE CurY := 1;
- #81: IF CurY < Unten-BigStep THEN
- Inc(CurY, BigStep) { <PgDn> }
- ELSE CurY := Unten;
- #132: CurY := 1; { <Ctrl>-<PgUp> }
- #118: CurY := Unten; { <Crtl>-<PgDn> }
- #15: BEGIN { <Shift>-<Tab> }
- IF CurX = 1 THEN BEGIN
- CurX := Rechts - AnzLetter + 1;
- IF CurY > 1 THEN Dec(CurY)
- ELSE CurY := Unten;
- END ELSE
- IF CurX < AnzLetter + 1 THEN
- CurX := 1
- ELSE Dec(CurX, AnzLetter);
- END;
- END;
- END;
- #13: IF CurY < Unten THEN BEGIN { <Enter> }
- Inc(CurY); CurX := 1;
- END;
- #32: BEGIN { <Space> }
- RestoreWindow; DrawNeu := TRUE;
- Inc(Position); MakeWindow(NormAttr);
- END;
- #9: IF CurX < Rechts - AnzLetter + 1 THEN { <Tab> }
- Inc(CurX, AnzLetter)
- ELSE BEGIN
- CurX := 1;
- IF CurY < Unten THEN Inc(CurY)
- ELSE CurY := 1;
- END;
- '+': IF (AnzLetter + 1) * LetterBreite + 4 < Rechts
- THEN BEGIN { Window verbreitern }
- RestoreWindow;
- Inc(AnzLetter);
- IF CurX + AnzLetter > Rechts THEN
- Dec(CurX);
- DrawNeu := TRUE;
- MakeWindow(NormAttr);
- END;
- '-': IF AnzLetter > 1 THEN BEGIN
- RestoreWindow; { Window verkleinern }
- Dec(AnzLetter); DrawNeu := TRUE;
- MakeWindow(NormAttr);
- END;
- 'S': Find; { Suchbegriff eingeben und suchen }
- 'W': FindWord; { weiter suchen }
- END;
- { prüfen, ob Window automatisch verschoben werden muß }
- IF CurY IN [WinY1..WinY2] THEN BEGIN
- DrawNeu := TRUE; RestoreWindow;
- MakeWindow(NormAttr);
- END;
- UNTIL ch = #27; { Ende mit <Escape> }
- RestoreWindow; { Bildschirm restaurieren, }
- GotoXY(CurXAlt, CurYAlt);{ Cursorposition restaurieren }
- END;
- END; { und Zoomer verlassen ... }
- {$F-}
-
- BEGIN
- IF AlreadyLoaded(ZoomID) THEN
- Writeln(Programm, ' ist bereits geladen!',
- ^M^J, 'Aktivieren Sie das Programm mit ',
- HotkeyName, '.')
- ELSE BEGIN
- IF PopUpInstalled (@Zoom, Hotkey, 1) THEN BEGIN
- Writeln(Programm, ' geladen',
- ^M^J, 'Aktivieren Sie das Programm mit ',
- HotkeyName);
- MakeResident(ZoomID);
- END ELSE
- Writeln(Programm, ' nicht installiert,', ^M^J,
- 'Fehler: Vermutlich zu wenig Hauptspeicher!');
- END;
- Writeln;
- Writeln('(c) 1990 Gerd Arnold & TOOLBOX');
- END.
- (* ------------------------------------------------------ *)
- (* Ende von ZOOMER.PAS *)