home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------ *)
- (* ASCII.PAS *)
- (* Speicherresidente ASCII-Tabelle *)
- (* Benutzung von Extended/Expanded Memory in TSR's *)
- (* Turbo Pascal Versionen 4.0 und 5.x *)
- (* Copyright (c) 1989 Karsten Gieselmann & TOOLBOX *)
- (* ------------------------------------------------------ *)
-
- PROGRAM Ascii;
-
- {B-,I-,R-,S-,V-} (* keine Laufzeitprüfungen! *)
- {$M 1024, 0, 0} (* wenig Stack, kein Heap! *)
-
- {.$DEFINE UseEMS} (* welcher Speicher soll benutzt werden? *)
- {.$DEFINE UseXMS}
- {.$DEFINE UseHMA}
- {$DEFINE UseRAM}
-
- USES (* benutzte Module *)
- {$IFDEF UseEMS} EMS, {$ENDIF}
- {$IFDEF UseXMS} XMS, {$ENDIF}
- {$IFDEF UseHMA} XMS, {$ENDIF}
- DOS, Utility;
-
- CONST (* Farbattribut für.... *)
- Normal = $07; (* ....normale Zeichen *)
- Bright = $0F; (* ....für Zeichencodes *)
- Select = $DF; (* ....das gewählte Zeichen *)
- Help = $1F; (* ....Kopf- und Fußzeile *)
- Frame = $0F; (* ....den Fensterrahmen *)
- ColSize = 35; (* Ausdehnung des Fensters *)
- RowSize = 24;
- XOfs = 46; (* linke oberen Fensterecke *)
- YOfs = 1;
-
- Hotkey = $7100; (* Aufruftaste: <Alt><F10> *)
- HotkeyName = '<Alt><F10>';
-
- TYPE
- Screen = ARRAY[1..25,1..80] OF WORD;
- Window = ARRAY[1..RowSize, 1..ColSize] OF WORD;
- ScreenPtr = ^Screen;
- VAR
- KbdBuffer : STRING[3]; (* zur Datenübernahme *)
- SaveInt16 : POINTER;
- PopupSS, PopupSP : WORD; (* Popup-Stapelkonfiguration *)
-
- (* ------- vom Speichermedium abhängige Routinen -------- *)
-
- {$IFDEF UseEMS} {$I ASCII.EMS} {$ENDIF}
- {$IFDEF UseXMS} {$I ASCII.XMS} {$ENDIF}
- {$IFDEF UseHMA} {$I ASCII.HMA} {$ENDIF}
- {$IFDEF UseRAM} {$I ASCII.RAM} {$ENDIF}
-
- (* ----------------- Interrupt-Handling ----------------- *)
-
- CONST
- InUse : BOOLEAN = FALSE; (* Interrupt schon aktiv? *)
- Unloaded : BOOLEAN = FALSE; (* TSR wieder entfernt? *)
- RecallPopup : BOOLEAN = FALSE; (* nochmal aufrufen? *)
- VAR
- SaveSS, SaveSP : WORD; (* Stapelkonfiguration *)
-
- FUNCTION ReadKeyWord : WORD;
- (* holt Tastencode von alter Interruptroutine *)
- INLINE($31/$C0/$9C/$FF/$1E/SaveInt16);
-
- PROCEDURE Popup; FORWARD;
-
- PROCEDURE Int16(BP : WORD); INTERRUPT;
- (* eigene Behandlungsroutine für den Tastatur-Interrupt *)
- TYPE
- IntRegisters = (* Registerbelegung beim Aufruf *)
- RECORD CASE BYTE OF
- 1 : (BP,ES,DS,DI,SI,DX,CX,BX,AX,IP,CS,Flags : WORD);
- 2 : (Dummy : ARRAY[1..5] of WORD;
- DL,DH,CL,CH,BL,BH,AL,AH : BYTE);
- END;
- VAR
- Regs : IntRegisters ABSOLUTE BP;
-
- PROCEDURE Chain(Regs : IntRegisters; Address : POINTER);
- (* setzt Interrupt-Ausführung bei "Address" fort. *)
- INLINE($5B/$58/$5E/$1F/$87/$5C/$0E/$87/$44/$10/$8B/
- $54/$16/$52/$9D/$8C/$DA/$FA/$8E/$D2/$89/$F4/
- $FB/$5D/$07/$1F/$5F/$5E/$5A/$59/$CB);
-
- PROCEDURE SwitchStack;
- (* schaltet auf programmeigenen Stapel um. *)
- INLINE($FA/$8C/$16/SaveSS/$89/$26/SaveSP/
- $8E/$16/PopupSS/$8B/$26/PopupSP/$FB);
-
- PROCEDURE RestoreStack;
- (* schaltet auf ursprünglichen Stapel zurück. *)
- INLINE($FA/$8E/$16/SaveSS/$8B/$26/SaveSP);
-
- BEGIN
- WITH Regs DO BEGIN
- IF (AH AND $EF = 1) AND (KbdBuffer <> '') THEN BEGIN
- AX := Ord(KbdBuffer[1]);
- Flags := Flags AND NOT FZero;
- END ELSE IF (AH AND $EF = 1) AND RecallPopup THEN BEGIN
- AX := Hotkey;
- Flags := Flags AND NOT FZero;
- END ELSE IF (AH AND $EF = 0) AND NOT InUse THEN BEGIN
- REPEAT
- IF KbdBuffer <> '' THEN BEGIN (* noch Daten da? *)
- AX := Ord(KbdBuffer[1]);
- Delete(KbdBuffer, 1, 1);
- END ELSE BEGIN
- IF RecallPopup THEN BEGIN
- AX := Hotkey;
- RecallPopup := FALSE;
- END ELSE BEGIN (* sonst Taste holen *)
- AX := ReadKeyWord;
- END;
- IF (AX = Hotkey) AND NOT Unloaded THEN BEGIN
- InUse := TRUE;
- SwitchStack; (* Stapel umschalten *)
- Popup; (* Pop-Up ausführen *)
- RestoreStack; (* Stapel restaurieren *)
- InUse := FALSE; (* Aufrufe wieder zulassen *)
- END;
- END;
- UNTIL (AX <> Hotkey) OR Unloaded;
- IF Unloaded THEN BEGIN (* Vektor zurücksetzen *)
- SetIntVec($16, SaveInt16);
- END;
- END ELSE BEGIN
- Chain(Regs, SaveInt16); (* weiter mit alter Routine *)
- END;
- END;
- END;
-
- (* ------------------- Pop-Up-Routine ------------------- *)
-
- PROCEDURE Popup;
- (* zeigt Ascii-Tabelle an, läßt einen Eintrag auswählen
- und übernimmt das Zeichen bzw. den zugehörigen Code
- in das gerade laufende Programm. *)
- CONST
- Left = #$CB; Right = #$CD; Up = #$C8;
- Down = #$D0; Home = #$C7; End_ = #$CF;
- PgUp = #$C9; PgDn = #$D1;
- Code : BYTE = 196; (* Blockgrafik-Zeichen *)
- VAR
- Row, Col, Save : BYTE;
- OctStr, DecStr, HexStr : STRING[3];
- Command : CHAR;
- CurrentPage : ScreenPtr;
-
- FUNCTION CurrentPageAddress : POINTER;
- (* ermittelt die Adresse der aktuellen Videoseite. *)
- VAR
- Regs : Registers;
- BEGIN
- Regs.AH := $0F;
- Intr($10, Regs);
- IF Regs.AL = 7 THEN BEGIN
- CurrentPageAddress := Ptr($B000, Regs.BH*1000);
- END ELSE BEGIN
- CurrentPageAddress := Ptr($B800, Regs.BH*1000);
- END;
- END;
-
- FUNCTION GetKey : CHAR;
- (* holt Tastencode; bei erweiterten Tasten (z.B. Funk-
- tions- oder Cursortasten, erster Code ist Nullzei-
- chen) wird das 8.Bit im Code gesetzt. *)
- VAR
- Key : WORD;
- BEGIN
- Key := ReadKeyWord;
- IF Lo(Key) = 0 THEN BEGIN (* erweiterter Code? *)
- GetKey := Chr(Hi(Key) or $80);
- END ELSE BEGIN
- GetKey := Chr(Lo(Key));
- END;
- END;
-
- PROCEDURE Num2Str(Num, Base : BYTE; VAR St : STRING);
- (* bewerkstelligt die Umwandlung des Codes in eine Zei-
- chenkette; die Auslegung als Prozedur mit Ergebnis-
- übergabe in einer VARiable spart Stapelspeicher ein. *)
- CONST
- Digit : ARRAY[0..15] OF CHAR = '0123456789ABCDEF';
- VAR
- d : BYTE;
- BEGIN
- St[0] := #3;
- FOR d:=3 DOWNTO 1 DO BEGIN
- St[d] := Digit[Num MOD Base];
- Num := Num DIV Base;
- END;
- END;
-
- PROCEDURE Poke(Col, Row : BYTE; VAR St : STRING);
- (* schreibt den aktuellen Zeichencode direkt in den
- Bildschimspeicher; um Stack zu sparen, wird "St" als
- Call-by-Reference-Parameter übergeben. *)
- VAR
- i, v : WORD;
- BEGIN
- FOR i:=1 TO Length(St) DO BEGIN
- v := Word(Bright)*256 + Ord(St[i]);
- CurrentPage^[YOfs+Row, XOfs+Col+i] := v;
- END;
- END;
-
- PROCEDURE ReleaseRAM(Segment : WORD);
- (* gibt den RAM-Speicherblock bei Segment:0 wieder frei *)
- VAR
- Regs : Registers;
- BEGIN
- Regs.AH := $49;
- Regs.ES := Segment;
- MsDos(Regs);
- END;
-
- PROCEDURE UnInstall;
- (* entfernt das Programm wieder aus dem Speicher. *)
- VAR
- CurrInt16 : POINTER;
- BEGIN
- GetIntVec($16, CurrInt16);
- IF CurrInt16 = @Int16 THEN BEGIN
- Unloaded := TRUE;
- DeallocateBuffers;
- ReleaseRAM(MemW[PrefixSeg:$2C]);
- ReleaseRAM(PrefixSeg);
- END ELSE BEGIN
- Write(^G);
- END;
- END;
-
- BEGIN
- CurrentPage := CurrentPageAddress; (* Bildschirmadresse *)
- SaveScreen(CurrentPage); (* Inhalt sichern *)
- DisplayAsciiTable(CurrentPage); (* Tabelle anzeigen *)
- Save := 0;
- REPEAT (* auswählen *)
- Col := XOfs + (Code mod 16 + 1)*2;
- Row := YOfs + (Code shr 4 + 3);
- Num2Str(Code, 8, OctStr); Poke( 7, 20, OctStr);
- Num2Str(Code, 10, DecStr); Poke(17, 20, DecStr);
- Num2Str(Code, 16, HexStr); Poke(28, 20, HexStr);
- CurrentPage^[Row,Col] := Word(Select)*256 + Code;
- Save := Code;
- Command := UpCase(GetKey);
- CASE Command OF (* Cursor bewegen *)
- Left : Dec(Code);
- Right : Inc(Code);
- Up : Dec(Code, 16);
- Down : Inc(Code, 16);
- Home : Code := (Code shr 4) shl 4;
- End_ : Code := (Code shr 4) shl 4 + 15;
- PgUp : Code := Code mod 16;
- PgDn : Code := Code mod 16 + 240;
- ^U : { Hier noch nichts machen! };
- END;
- CurrentPage^[Row,Col] := Word(Normal)*256 + Save;
- UNTIL Pos(Command, ^[^M^J^U^O^D^H'ODH') > 0;
- RestoreScreen(CurrentPage); (* alter Bildschirminhalt *)
- CASE Command OF (* Daten übergeben *)
- ^J, ^M : KbdBuffer := Chr(Code);
- ^D, 'D': KbdBuffer := DecStr;
- ^H, 'H': KbdBuffer := HexStr;
- ^O, 'O': KbdBuffer := OctStr;
- ^U : UnInstall;
- END;
- RecallPopup := (Pos(Command, ^J^O^D^H) > 0);
- END;
-
- (* ----------------- Installationsteil ------------------ *)
-
- PROCEDURE SetupAsciiTable;
- (* Aufbau der später anzuzeigenden Ascii-Tabelle. *)
- CONST
- UpperLeft = #218; Horizontal = #196; (* Rahmenzeichen *)
- UpperRight = #191; LowerLeft = #192;
- Vertical = #179; LowerRight = #217;
- Header : String[33] = ' Anwahl mit Cursortasten ';
- Footer : String[33] = ' Return:Zeichen O,D,H:Code ';
- Codes : String[33] = ' Okt: Dez: Hex: ';
- VAR
- Row, Col : BYTE; (* Schleifenvariablen *)
- BEGIN
- FOR Row:=3 TO RowSize-2 DO BEGIN (* Inneres löschen *)
- FOR Col:=2 TO ColSize-1 DO BEGIN
- SetTable(Col, Row, Normal, ' ');
- END;
- END;
- SetTable( 1, 1, Frame, UpperLeft); (* Rahmen *)
- SetTable(ColSize, 1, Frame, UpperRight);
- SetTable( 1, RowSize, Frame, LowerLeft);
- SetTable(ColSize, RowSize, Frame, LowerRight);
- FOR Col:=2 TO ColSize-1 DO BEGIN
- SetTable(Col, 1, Frame, Horizontal);
- SetTable(Col, RowSize, Frame, Horizontal);
- SetTable(Col, 2, Help, Header[Col-1]);
- SetTable(Col, RowSize-3, Normal,Codes[Col-1]);
- SetTable(Col, RowSize-1, Help, Footer[Col-1]);
- END;
- FOR Row:=2 TO RowSize-1 DO BEGIN
- SetTable( 1, Row, Frame, Vertical);
- SetTable(ColSize, Row, Frame, Vertical);
- END;
- FOR Row:=0 TO 15 DO BEGIN (* Zeichen eintragen *)
- FOR Col:=0 TO 15 DO BEGIN
- SetTable(Col*2+3, Row+4, Normal, Chr(Row*16+Col));
- END;
- END;
- END;
-
- BEGIN
- StartUp('ASCII - Speicherresidente Ascii-Tabelle');
- AllocateBuffers; (* Speicherplatz organisieren *)
- SetupAsciiTable; (* Tabelle aufbauen *)
- PopupSS := SSeg; (* Stapelkonfiguration merken *)
- PopupSP := SPtr;
- KbdBuffer := ''; (* Tastaturverwaltung initialisieren *)
- GetIntVec($16, SaveInt16); (* Int16-Vektor sichern *)
- SetIntVec($16, @Int16); (* eigenen Handler aktivieren *)
- SetIntVec($00, SaveInt00); (* Vektoren restaurieren *)
- {$IFNDEF Ver40}
- SetIntVec($3F, SaveInt3F);
- {$ENDIF}
- Write('Aufruf mit ', HotkeyName);
- WriteLn(', Entfernen mit <Ctrl><U>.');
- PrepareExit;
- Keep(0); (* resident machen *)
- END.
- (* ------------------------------------------------------ *)
- (* Ende von ASCII.PAS *)