AND und EventMultiple in LPR-Modula-2

Das Public Domain-Modula-2 der Universität München hat fast vollständige AES- und VDI-Bibliotheken. Außerdem befinden sich auf der Diskette noch zwei Module (Application und WindowBase), die eine recht komfortable Zwischenschicht zur GEM-Programmierung bieten.

So erlaubt der Variante Record messagetype eine übersichtlichere Abarbeitung von Nachrichten als die allgemein in (C-)Programmen übliche Definition eines Arrays. Nur die Abfrage von EventMulti wird von Application leider nicht unterstützt. Bekanntlich können hier auch mehrere Ereignisse gleichzeitig auftreten, die abgefragt werden müssen. C- und (Pure-)Pascal-Programmierer können hier mit AND bitweise vergleichen. Dies ist in LPR-Modula aber so nicht möglich, da AES.EventMultiple einen Integerwert zurückliefert, und wegen der strengen Typbindung erlaubt Modula hierauf kein AND. Dafür bietet es den Standardtyp BITSET, der gerade für solche Operationen gedacht ist. Nur ... wie erledigen wir die Typumwandlung von INTEGER in BITSET? Den naiven Ansatz überden Joker-Datentyp WORD

PROCEDURE bitset(a : WORD) : WORD;
BEGIN 
    RETURN BITSET(a);
END bitset;

den z.B. Megamax-Modula-2 erlaubt, weist das LPR-Sy-stem mit der Meldung „Incompatible Operand-Type“ zurück. Eine auch mit dem LPR-Modula funktionierende Lösung hat R. Tolksdorf in der ST-Computer 11/1990 vorgestellt, die, von mir etwas erweitert, eine genauso einfache EventMulti-ple-Abrage wie in C erlaubt. Wir importieren dazu aus dem Pseudo-Modul SYSTEM die Prozedur VAL, die von Wirth explizit für das Type Casting vorgesehen ist. (Doch Vorsicht; VAL ist in hohem Maße implementierungsabhängig, mit einem anderen Modula-System muß es so nicht unbedingt funktionieren. Daher geht auch kaum ein Modula-Lehrbuch näher auf VAL ein.) Dann definieren wir die folgende Prozedur:

FROM SYSTEM IMPORT WORD, VAL;
...
PROCEDURE and(a, b : WORD) ; BOOLEAN;
    VAR c ; BITSET;
    BEGIN
        c := VAL(BITSET, a) * VAL(BITSET, b);
        IF c <> 0 THEN RETURN TRUE ELSE RETURN FALSE;
    END and;
...

Der Mengenoperator '*' ist der Durchschnittsoperator, genau dies entspricht einem arithmetischen „BitAND“. Nun wird die Abfrage von EventMultiple genauso einfach wie in C-Programmen, denn die Konstanten sind alle schon in AESBase definiert (s. Listing 1).

Der Einschluß der Ereignisbehandlung in WindowUpdate (BeginUpdate) und WindowUpdate(EndUpdate) muß übrigens immer erfolgen, auch wenn man aus den Kommentaren zum Definitionsmodul von Application etwas anders herauslesen könnte. Und natürlich ist niemand gezwungen, die Module Application und WindowBase zu benutzen. Man kann auch alle AES-Funktionen direkt aus dem Modul AES importieren. Dann funktioniert das gesamte GEM-Handling wie in den (C-)Lehrbüchern zu GEM beschrieben. Allerdings muß man dann auf einige Vorzüge dieser Zwischenmodule (z.B. automatisches Abarbeiten der Rechteckliste) verzichten.


FROM SYSTEM IMPORT WORD, VAL, ADR;
FROM AES IMPORT EventMultiple, WindowUpdate;
FROM AESBase IMPORT (* nur Konstanten *)
MessageEvent, TimerEvent, ..., EndUpdate, BeginUpdate, ...;
FROM Application IMPORT messagetype, ...;
FROM WindowBase IMPORT ...;
...
VAR mBuf : messagetype;
events, flag, mx, my, mbutton, mstate, Scancode, 
mclicks : INTEGER;
...
flag := MessageEvent + TimerEvent; (* zum Beispiel *)
...
(* Event Loop: *)
events := EventMultiple(flag,
        0,0,0,
        0,0,0,0,0,
        0,0,0,0,0,
        ADR(mBuf), (* Message-Event *)
        10000,0, (* Timer-Event *)
        mx, my,
        mbutton, mstate, 
        scancode, mclicks);
WindowUpdate(BeginUpdate);
IF and(events, MesageEvent) THEN ...
    (* Menü- und Fensternachrichten auswerten *)
END;
IF and(events, TimerEvent) THEN ...
    (* Timer-Ereignisse auswerten *)
END;
WindowUpdate(EndUpdate);

Jörg Kantel
Aus: ST-Computer 03 / 1993, Seite 82

Links

Copyright-Bestimmungen: siehe Über diese Seite