home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1990 / 12 / grdlagen / mousekey.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1990-09-10  |  18.1 KB  |  597 lines

  1. (* ------------------------------------------------------ *)
  2. (*                     MOUSEKEY.PAS                       *)
  3. (*    Stellt Objekte für EventHandling zur Verfügung.     *)
  4. (*       (c) 1990 Raimond Reichert & TOOLBOX              *)
  5. (* ------------------------------------------------------ *)
  6. UNIT MouseKey;
  7.  
  8. INTERFACE
  9.  
  10. USES Dos;
  11.  
  12. CONST
  13.   MaxEvents   =  100;       { max. Anzahl Events           }
  14.   EvNoEv      =    0;       { kein Event liegt vor         }
  15.   EvMouMove   =    1;       { Maus wurde bewegt            }
  16.   EvLeftPress =    2;       { linke MausTaste gedrückt     }
  17.   EvLeftRel   =    4;       { linke MausTaste losgelassen  }
  18.   EvRightPress=    8;       { rechte Taste gedrückt        }
  19.   EvRightRel  =   16;       { rechte Taste losgelasssen    }
  20.   EvKeyPressed=  256;       { "normale" Taste gedrückt     }
  21.   EvKeyUnknown=  512;       { unbekannt Taste gedrückt     }
  22.   EvKeyState  = 1024;       { Statustaste betätigt         }
  23.   EvMouAll    =   31;       { alle Mausereignisse          }
  24.   EvKeyAll    = 1792;       { alle Tastaturereignisse      }
  25.   EvAll       = 1823;       { alle Ereignisse              }
  26.  
  27.   IndexArray  : ARRAY [1..9] OF WORD =
  28.                   (0, 1, 2, 4, 8, 16, 256, 512, 1024);
  29.  
  30.   RightShift  =   1;        { Bitwerte für die einzelnen   }
  31.   LeftShift   =   2;        { Statustasten                 }
  32.   Ctrl        =   4;
  33.   Alt         =   8;
  34.   ScrollLock  =  16;
  35.   NumLock     =  32;
  36.   CapsLock    =  64;
  37.   Insert      = 128;
  38.  
  39.   TakeOut     : BOOLEAN = FALSE;
  40.                           { aus Tastaturpuffer entfernen ? }
  41.  
  42. TYPE
  43.   EventObj = OBJECT
  44.  
  45.     Time            : LONGINT;      { Zeitpunkt des Events }
  46.     EventType       : WORD;         { Art des Events       }
  47.     x, y, Buttons   : INTEGER;
  48.     Key             : WORD;
  49.     ScanCode, State : BYTE;
  50.     StateKey        : BYTE;
  51.   END;
  52.  
  53.   EventObjArray = ARRAY [1..MaxEvents] OF EventObj;
  54.   EventQueuePtr = ^EventQueue;
  55.  
  56.   EventQueue    = OBJECT
  57.  
  58.     NextToCall, CameLastIn : INTEGER;
  59.     Queue                  : EventObjArray;   { die Events }
  60.   END;
  61.  
  62.   HandlerProc = PROCEDURE(VAR Event : EventObj);
  63.  
  64.   HandlerObj  = OBJECT
  65.  
  66.     Call    : BOOLEAN;
  67.     Handler : HandlerProc
  68.   END;
  69.  
  70.   HandlerArray = ARRAY [1..16] OF HandlerObj;
  71.   MouseObjPtr  = ^MouseObj;
  72.  
  73.   MouseObj    = OBJECT                  { für Mausabfragen }
  74.  
  75.     Regs      : Registers;
  76.     Avail,                              { Maus vorhanden ? }
  77.     Visible,                            { Maus sichtbar ?  }
  78.     TextModus : BOOLEAN;                { Textmodus ?      }
  79.  
  80.     CONSTRUCTOR Init;
  81.     PROCEDURE  Hide;                                VIRTUAL;
  82.     PROCEDURE  Show;                                VIRTUAL;
  83.     PROCEDURE  SetArea(x1, y1, x2, y2 : INTEGER);   VIRTUAL;
  84.     PROCEDURE  SetSpeed(xs, ys : INTEGER);          VIRTUAL;
  85.     PROCEDURE  SetMouse(x, y : INTEGER);
  86.     PROCEDURE  TextMouse(Chr : CHAR; Col, BckCol : BYTE);
  87.     FUNCTION   GetX : BYTE;                         VIRTUAL;
  88.     FUNCTION   GetY : BYTE;                         VIRTUAL;
  89.     DESTRUCTOR Done;                                VIRTUAL;
  90.   END;
  91.  
  92.   EventHandlerObjPtr = ^EventHandlerObj;
  93.  
  94.   EventHandlerObj    = OBJECT
  95.  
  96.     MouQueue     : EventQueuePtr;
  97.     KeyQueue     : EventQueuePtr;
  98.     TextModus    : BOOLEAN;
  99.     AktState,
  100.     AktMouX,
  101.     AktMouY      : BYTE;
  102.     HandlerTable : HandlerArray;
  103.  
  104.     CONSTRUCTOR Init;
  105.     PROCEDURE   KeybHandler(Key : BYTE);            VIRTUAL;
  106.     PROCEDURE   MouseHandler;                       VIRTUAL;
  107.     PROCEDURE   PutEvInQueue(Queue : EventQueuePtr;
  108.                              Event : EventObj);     VIRTUAL;
  109.     PROCEDURE   GetEvFromQueue(VAR Queue : EventQueuePtr;
  110.                                VAR Event : EventObj);
  111.                                                     VIRTUAL;
  112.     PROCEDURE   PeekEvFromQueue(VAR Queue : EventQueuePtr;
  113.                                 VAR Event : EventObj);
  114.                                                     VIRTUAL;
  115.     PROCEDURE   PeekEvent(VAR Event : EventObj);    VIRTUAL;
  116.     PROCEDURE   GetEvent(VAR Event : EventObj);     VIRTUAL;
  117.     PROCEDURE   WaitForEvent(WaitForEv : INTEGER;
  118.                              VAR Event : EventObj); VIRTUAL;
  119.     FUNCTION    GetEvIndex(EventType : WORD) : BYTE;
  120.                                                     VIRTUAL;
  121.     PROCEDURE   RegisterHandler(Event      : WORD;
  122.                                 NewHandler : HandlerProc);
  123.                                                     VIRTUAL;
  124.     PROCEDURE   DeRegisterHandler(Event : WORD);    VIRTUAL;
  125.     DESTRUCTOR  Done;                               VIRTUAL;
  126.   END;
  127.  
  128. VAR
  129.   Mouse  : MouseObjPtr;      { ACHTUNG: Kon- bzw Destruktor}
  130.   EvHand : EventHandlerObjPtr;      { NICHT aufrufen !     }
  131.  
  132.  
  133. IMPLEMENTATION
  134.  
  135. {$L MOUSEKEY}
  136.  
  137. {$F+}
  138.  
  139.   PROCEDURE NewMouHandler;  EXTERNAL;
  140.                        { wird vom Mausinterrupt aufgerufen }
  141.  
  142.   PROCEDURE NewKeybHandler; EXTERNAL;
  143.                                   { ersetzt Interupt 09hex }
  144. {$F-}
  145.  
  146. VAR
  147.   KeybState : BYTE ABSOLUTE $40:$17;      { Tastaturstatus }
  148.   BiosTime  : LONGINT ABSOLUTE $40:$6C;   { Zeit in Ticks  }
  149.   OldInt09,                { zum Sichern der alten Adresse }
  150.   OldExitProc : POINTER;
  151.   NewFlags,       { werden gesetzt, wenn Mausereignis ein- }
  152.   NewButtons,     { trifft. Nicht als Parameter, da sonst  }
  153.   NewX,           { Gefahr eines "Stack Overflow" .        }
  154.   NewY        : INTEGER;
  155.  
  156.  
  157.   CONSTRUCTOR MouseObj.Init;
  158.   BEGIN
  159.     Regs.AX   := $00;
  160.     Intr($33, Regs);
  161.     Avail     := (Regs.AX = $FFFF);
  162.     Visible   := FALSE;
  163.     TextModus := TRUE
  164.   END;
  165.  
  166.   PROCEDURE MouseObj.Hide;
  167.   BEGIN
  168.     IF Avail AND Visible THEN BEGIN
  169.       Regs.AX := $02;
  170.       Intr($33, Regs);
  171.       Visible := FALSE
  172.     END;
  173.   END;
  174.  
  175.   PROCEDURE MouseObj.Show;
  176.   BEGIN
  177.     IF Avail AND NOT Visible THEN BEGIN
  178.       Regs.AX := $01;
  179.       Intr($33, Regs);
  180.       Visible := TRUE;
  181.     END;
  182.   END;
  183.  
  184.   PROCEDURE MouseObj.SetArea(x1, y1, x2, y2 : INTEGER);
  185.   BEGIN
  186.     IF Avail THEN BEGIN
  187.       Regs.AX := $07;
  188.       IF TextModus THEN BEGIN
  189.         Regs.CX := Pred(x1) SHL 3;
  190.         Regs.DX := Pred(x2) SHL 3;
  191.       END ELSE BEGIN
  192.         Regs.CX := x1;
  193.         Regs.DX := x2;
  194.       END;
  195.       Intr($33, Regs);
  196.       Regs.AX := $08;
  197.       IF TextModus THEN BEGIN
  198.         Regs.CX := Pred(y1) SHL 3;
  199.         Regs.DX := Pred(y2) SHL 3;
  200.       END ELSE BEGIN
  201.         Regs.CX := y1;
  202.         Regs.DX := y2;
  203.       END;
  204.       Intr($33, Regs);
  205.     END;
  206.   END;
  207.  
  208.   PROCEDURE MouseObj.SetSpeed(xs, ys : INTEGER);
  209.   BEGIN
  210.     IF Avail THEN BEGIN
  211.       Regs.AX := $0F;
  212.       Regs.CX := xs;
  213.       Regs.DX := ys;
  214.       Intr($33, Regs);
  215.     END;
  216.   END;
  217.  
  218.   PROCEDURE MouseObj.SetMouse(x, y : INTEGER);
  219.   BEGIN
  220.     Regs.AX := $04;
  221.     IF TextModus THEN BEGIN
  222.       Regs.CX := x SHR 3;
  223.       Regs.DX := y SHR 3;
  224.     END ELSE BEGIN
  225.       Regs.CX := Pred(x);
  226.       Regs.DX := Pred(y);
  227.     END;
  228.     Intr($33, Regs);
  229.   END;
  230.  
  231.   PROCEDURE MouseObj.TextMouse(Chr         : CHAR;
  232.                                Col, BckCol : BYTE);
  233.   VAR
  234.     attr : INTEGER;
  235.   BEGIN
  236.     IF TextModus THEN BEGIN
  237.       Regs.AX := $0A;
  238.       Regs.BX := $00;
  239.       Attr := Col OR (BckCol SHL 4);
  240.       IF Col > 15 THEN Attr := Attr OR 128;
  241.       Regs.CX := Attr SHL 8;
  242.       Regs.DX := Regs.CX + Ord(Chr);
  243.       Intr($33, Regs)
  244.     END;
  245.   END;
  246.  
  247.   FUNCTION MouseObj.GetX : BYTE;
  248.   BEGIN
  249.     IF Avail THEN BEGIN
  250.       Regs.AX := $03;
  251.       Intr($33, Regs);
  252.       IF TextModus THEN
  253.         GetX := Succ(Regs.CX SHR 3)
  254.       ELSE
  255.         GetX := Regs.CX;
  256.     END;
  257.   END;
  258.  
  259.   FUNCTION MouseObj.GetY : BYTE;
  260.   BEGIN
  261.     IF Avail THEN BEGIN
  262.       Regs.AX := $03;
  263.       Intr($33, Regs);
  264.       IF TextModus THEN
  265.         GetY := Succ(Regs.DX SHR 3)
  266.       ELSE
  267.         GetY := Regs.DX;
  268.     END;
  269.   END;
  270.  
  271.   DESTRUCTOR MouseObj.Done;
  272.   BEGIN
  273.     Hide;
  274.   END;
  275.  
  276.  
  277.   CONSTRUCTOR EventHandlerObj.Init;
  278.   (* Initialisiert EventHandlerObj. ACHTUNG: NICHT auf-   *)
  279.   (* rufen, da der Init-Teil der Unit ihn aufruft.        *)
  280.   VAR
  281.     Regs : Registers;
  282.     i    : BYTE;
  283.   BEGIN
  284.     New(MouQueue);        { Anlegen der Ereignisschlangen  }
  285.     New(KeyQueue);
  286.     IF (MouQueue = NIL) OR (KeyQueue = NIL) THEN Fail;
  287.     WITH MouQueue^ DO BEGIN
  288.       NextToCall := 1;   CameLastIn := 1;
  289.     END;
  290.     WITH KeyQueue^ DO BEGIN
  291.       NextToCall := 1;   CameLastIn := 1;
  292.     END;
  293.     TextModus := TRUE;
  294.     AktState  := KeybState;
  295.     FOR i := 1 TO 16 DO         { kein Handler installiert }
  296.       HandlerTable[i].Call := FALSE;
  297.     IF Mouse^.Avail THEN BEGIN
  298.       AktMouX := Mouse^.GetX;         { auch für Vergleich }
  299.       AktMouY := Mouse^.GetY;
  300.       Regs.AX := $C;      { Funktion Handler installieren  }
  301.       Regs.CX := EvMouAll;  { für jegliche Mausereignisse  }
  302.       Regs.DX := Ofs(NewMouHandler);
  303.       Regs.ES := Seg(NewMouHandler);
  304.       Intr($33, Regs);                      { installieren }
  305.     END;
  306.   END;
  307.  
  308.   PROCEDURE EventHandlerObj.KeybHandler (Key : BYTE);
  309.   (* Wird von der Prozedur "NewKeybHandler" aufgerufen,   *)
  310.   (* die den Interrupt 09hex ersetzt.                     *)
  311.   (* Darf NICHT vom Programm aufgerufen werden!           *)
  312.   VAR
  313.     Event      : EventObj;
  314.     Regs       : Registers;
  315.     NewKbState : BYTE;
  316.   BEGIN
  317.     Event.Time := BiosTime;    { Zeitpunkt des Eintreffens }
  318.     Regs.AH    := $11;         { liegt Tastendruck vor ?   }
  319.     Intr ($16, Regs);
  320.     IF (Regs.Flags AND FZero) = 0 THEN BEGIN       { ja... }
  321.       IF TakeOut THEN BEGIN { aus Tastaturpuffer entfernen }
  322.         Regs.AH := $10;
  323.         Intr($16, Regs)     { ja, abholen                  }
  324.       END ELSE BEGIN
  325.         Regs.AH := $11;     { nein, nur abfragen           }
  326.         Intr($16, Regs)
  327.       END;
  328.       IF (Regs.AL = 0) OR (Regs.AL = 224) THEN
  329.         Event.Key := Regs.AH + 256
  330.       ELSE
  331.         Event.Key := Regs.AL;
  332.       Event.EventType := EvKeyPressed;
  333.       PutEvInQueue(KeyQueue, Event);
  334.     END ELSE BEGIN         { nein,nichts im Tastaturpuffer }
  335.       NewKbState := KeybState;              { Neuer Status }
  336.       IF (AktState <> NewKbState) THEN BEGIN
  337.         IF (AktState < NewKbState) THEN BEGIN
  338.           Event.StateKey := AktState XOR NewKbState;
  339.           IF (Event.StateKey <> Insert) THEN BEGIN
  340.             Event.EventType := EvKeyState;
  341.             PutEvInQueue(KeyQueue, Event);
  342.           END;
  343.         END;
  344.       END ELSE BEGIN          { keine Statustaste gedrückt }
  345.         IF (Key < 128) THEN BEGIN
  346.           Event.EventType := EvKeyUnknown;
  347.           Event.ScanCode  := Key;
  348.           Event.State     := NewKbState;
  349.           PutEvInQueue(KeyQueue, Event)
  350.         END;
  351.       END;
  352.       AktState := NewKbState;      { neuen Status behalten }
  353.     END;
  354.   END;
  355.  
  356.   PROCEDURE EventHandlerObj.MouseHandler;
  357.   VAR
  358.     Event   : EventObj;
  359.     i, Mask : INTEGER;
  360.   BEGIN
  361.     WITH Event DO BEGIN
  362.       Time := BiosTime;           { die neuesten Mausdaten }
  363.       IF TextModus THEN BEGIN
  364.         x := Succ(NewX SHR 3);  y := Succ(NewY SHR 3);
  365.       END ELSE BEGIN
  366.         x := NewX;              y := NewY
  367.       END;
  368.       Buttons := NewButtons;
  369.     END;
  370.     Mask := 1;
  371.     FOR i := 0 TO 5 DO BEGIN
  372.       IF NOT ((NewFlags AND Mask = 0) OR
  373.              ((Mask = EvMouMove)      AND
  374.              ((Event.X = AktMouX)     AND
  375.               (Event.Y = AktMouY)))) THEN BEGIN
  376.         Event.EventType := Mask;
  377.         PutEvInQueue(MouQueue, Event);
  378.       END;
  379.       Mask := Mask SHL 1;
  380.     END;
  381.     AktMouX := Event.X;        { in die globalen Variablen }
  382.     AktMouY := Event.Y;        { übernehmen                }
  383.   END;
  384.  
  385.   PROCEDURE EventHandlerObj.PutEvInQueue
  386.                                      (Queue : EventQueuePtr;
  387.                                       Event : EventObj);
  388.   BEGIN
  389.     WITH Queue^ DO BEGIN
  390.       Queue [CameLastIn] := Event;
  391.       Inc(CameLastIn);
  392.       IF CameLastIn > MaxEvents THEN CameLastIn := 1;
  393.            { Falls ein Überlauf stattgefunden hat, so wird }
  394.            { wieder vorne angefangen, in die Queue einzu-  }
  395.            { tragen, daher MaxEvents gross genug wählen,   }
  396.            { damit keine Events überschrieben werden       }
  397.     END;
  398.   END;
  399.  
  400.   PROCEDURE EventHandlerObj.GetEvFromQueue
  401.                                  (VAR Queue : EventQueuePtr;
  402.                                   VAR Event : EventObj);
  403.   BEGIN
  404.     WITH Queue^ DO
  405.       IF NextToCall=CameLastIn THEN BEGIN
  406.         { noch kein Event, dann }
  407.         Event.Time      := MaxLongInt;    { ungültige Zeit }
  408.         Event.EventType := EvNoEv;        { und kein Event }
  409.       END ELSE BEGIN
  410.         Event := Queue [NextToCall];
  411.         IF (NextToCall = MaxEvents) THEN
  412.           NextToCall := 1
  413.         ELSE
  414.           Inc(NextToCall);
  415.       END;
  416.   END;
  417.  
  418.   PROCEDURE EventHandlerObj.PeekEvFromQueue
  419.                                  (VAR Queue : EventQueuePtr;
  420.                                   VAR Event : EventObj);
  421.   BEGIN
  422.     WITH Queue^ DO
  423.       IF NextToCall = CameLastIn THEN BEGIN
  424.         Event.Time      := MaxLongInt;
  425.         Event.EventType := EvNoEv
  426.       END ELSE
  427.         Event := Queue [NextToCall]
  428.   END;
  429.  
  430.   PROCEDURE EventHandlerObj.GetEvent(VAR Event : EventObj);
  431.   VAR
  432.     MouEvent, KeyEvent : EventObj;
  433.   BEGIN
  434.     REPEAT
  435.       PeekEvFromQueue(MouQueue, MouEvent);
  436.       PeekEvFromQueue(KeyQueue, KeyEvent);
  437.     UNTIL (MouEvent.EventType <> EvNoEv) OR
  438.           (KeyEvent.EventType <> EvNoEv);
  439.     IF (KeyEvent.Time >= MouEvent.Time) THEN
  440.       GetEvFromQueue(MouQueue, Event)
  441.     ELSE
  442.       GetEvFromQueue(KeyQueue, Event);
  443.   END;
  444.  
  445.   PROCEDURE EventHandlerObj.PeekEvent(VAR Event : EventObj);
  446.   VAR
  447.     MouEvent, KeyEvent : EventObj;
  448.   BEGIN
  449.     PeekEvFromQueue(MouQueue, MouEvent);
  450.     PeekEvFromQueue(KeyQueue, KeyEvent);
  451.     IF (KeyEvent.Time >= MouEvent.Time) THEN
  452.       Event := MouEvent
  453.     ELSE
  454.       Event := KeyEvent;
  455.   END;
  456.  
  457.   PROCEDURE EventHandlerObj.WaitForEvent
  458.                                      (WaitForEv : INTEGER;
  459.                                       VAR Event : EventObj);
  460.   VAR
  461.     EvIndex  : BYTE;
  462.   BEGIN
  463.     REPEAT
  464.       GetEvent(Event);
  465.       EvIndex := GetEvIndex(Event.EventType);
  466.       IF (HandlerTable[EvIndex].Call) THEN
  467.         HandlerTable[EvIndex].Handler(Event)
  468.     UNTIL (Event.EventType AND WaitForEv <> 0);
  469.     Event := Event;
  470.   END;
  471.  
  472.   FUNCTION EventHandlerObj.GetEvIndex
  473.                                   (EventType : WORD) : BYTE;
  474.   (* Liefert den Index, d.h. die Position eines Handlers  *)
  475.   (* für "EventType" in einem Array "HandlerArray" zurück *)
  476.   VAR
  477.     i, Index : BYTE;
  478.   BEGIN
  479.     Index := 0;
  480.     FOR i := 1 TO 9 DO
  481.       IF EventType=IndexArray[i] THEN Index := i;
  482.     GetEvIndex := Index;
  483.   END;
  484.  
  485.   PROCEDURE EventHandlerObj.RegisterHandler
  486.                    (Event : WORD; NewHandler : HandlerProc);
  487.   (* Installiert Handler NewHandler für Eventart "Event". *)
  488.   (* Die Abfragen sind notwendig, damit "NewHandler"      *)
  489.   (* auch für alle Mausereignisse eingetragen wird.       *)
  490.   VAR
  491.     i : INTEGER;
  492.   BEGIN
  493.     IF (Event = EvMouAll) OR (Event = EvKeyAll) OR
  494.        (Event = EvAll) THEN BEGIN
  495.       IF (Event = EvMouAll) OR (Event = EvAll) THEN
  496.         FOR i := 2 TO 6 DO
  497.           WITH HandlerTable [i] DO BEGIN
  498.             Handler := NewHandler;
  499.             Call    := TRUE;
  500.           END;
  501.       IF (Event = EvKeyAll) OR (Event = EvAll) THEN
  502.         FOR i := 7 TO 9 DO
  503.           WITH HandlerTable [i] DO BEGIN
  504.             Handler := NewHandler;
  505.             Call    := TRUE
  506.           END;
  507.     END ELSE
  508.       WITH HandlerTable [GetEvIndex (Event)] DO BEGIN
  509.         Handler := NewHandler;
  510.         Call := TRUE;
  511.       END;
  512.   END;
  513.  
  514.   PROCEDURE EventHandlerObj.DeRegisterHandler(Event : WORD);
  515.   VAR
  516.     i : INTEGER;
  517.   BEGIN
  518.     IF (Event = EvMouAll) OR (Event = EvKeyAll) OR
  519.        (Event = EvAll) THEN BEGIN
  520.       IF (Event = EvMouAll) OR (Event = EvAll) THEN
  521.         FOR i := 2 TO 6 DO
  522.           WITH HandlerTable[i] DO Call := FALSE;
  523.       IF (Event = EvKeyAll) OR (Event = EvAll) THEN
  524.         FOR i := 7 TO 7 DO
  525.           WITH HandlerTable[i] DO Call := FALSE;
  526.     END ELSE
  527.       WITH HandlerTable[GetEvIndex(Event)] DO
  528.         Call := FALSE
  529.   END;
  530.  
  531.   DESTRUCTOR EventHandlerObj.Done;
  532.   BEGIN
  533.     IF MouQueue <> NIL THEN Dispose(MouQueue);
  534.     IF KeyQueue <> NIL THEN Dispose(KeyQueue);
  535.   END;
  536.  
  537. {F+}
  538.   PROCEDURE MouKeyExit;
  539. {$F-}
  540.   (* Neue Exitprozedur, die den Speicher des Mausobjekts  *)
  541.   (* wieder freigibt und verbogene Zeiger zurücksetzt.    *)
  542.   VAR
  543.     Regs : Registers;
  544.   BEGIN
  545.     SetIntVec($09, OldInt09);
  546.     IF Mouse <> NIL THEN Mouse^.Done;
  547.     Regs.AX := $00;                { Maushandler entfernen }
  548.     Intr($33, Regs);
  549.     IF EvHand <> NIL THEN EvHand^.Done;
  550.     ExitProc := OldExitProc;
  551.   END;
  552.  
  553.   PROCEDURE CallKeybHandler(Key : BYTE);
  554.   (* Wird von dem Interruptersatz für Int 09hex aus       *)
  555.   (* dem Assemblermodul heraus aufgerufen und ruft        *)
  556.   (* ihrerseits "EvHand.KeybHandler".                     *)
  557.   BEGIN
  558.     EvHand^.KeybHandler(Key);
  559.   END;
  560.  
  561.   PROCEDURE CallMouHandler(NF, NB, NX, NY : INTEGER);
  562.   (* Wird von dem installierten Maushandler aus dem       *)
  563.   (* Assemblermodul aufgerufen und startet den            *)
  564.   (* Maushandler von "EvHand". Die Parameter werden       *)
  565.   (* wegen der Gefahr eines Stacküberlaufs in globalen    *)
  566.   (* Variablen gespeichert. Der Maushandler von "EvHand^" *)
  567.   (* muß diese abfragen.                                  *)
  568.   BEGIN
  569.     NewButtons := NB;
  570.     NewFlags   := NF;
  571.     NewX       := NX;
  572.     NewY       := NY;
  573.     EvHand^.MouseHandler;
  574.   END;
  575.  
  576. {$F+}
  577.   FUNCTION HeapFunc(Size : WORD) : INTEGER;
  578. {$F-}
  579.   BEGIN
  580.     HeapFunc := 1;
  581.   END;
  582.  
  583. BEGIN
  584.   HeapError := @HeapFunc;
  585.   Mouse     := New(MouseObjPtr, Init);
  586.   EvHand    := New(EventHandlerObjPtr, Init);
  587.   IF (Mouse <> NIL) AND (EvHand <> NIL) THEN BEGIN
  588.     OldExitProc := ExitProc;
  589.     ExitProc    := @MouKeyExit;
  590.     GetIntVec($09, OldInt09);
  591.     SetIntVec($09, @NewKeybHandler);
  592.   END;
  593. END.
  594. (* ------------------------------------------------------ *)
  595. (*                Ende von MOUSEKEY.PAS                   *)
  596.  
  597.