Skip to content

Instantly share code, notes, and snippets.

@be9
Created December 9, 2008 13:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save be9/33891 to your computer and use it in GitHub Desktop.
Save be9/33891 to your computer and use it in GitHub Desktop.
Console library for Modula-2
xc =m test.mod
DEFINITION MODULE Console;
IMPORT Windows;
TYPE ATTRIBUTE = Windows.CHAR_ATTRIBUTES_SET;
EVENT = Windows.INPUT_RECORD;
(* colors *)
CONST
FG_BLACK = ATTRIBUTE{}; (* 0 *)
FG_BLUE = Windows.FOREGROUND_BLUE; (* 1 *)
FG_GREEN = Windows.FOREGROUND_GREEN; (* 2 *)
FG_CYAN = FG_BLUE + FG_GREEN; (* 3 *)
FG_RED = Windows.FOREGROUND_RED; (* 4 *)
FG_PINK = FG_RED + FG_BLUE; (* 5 *)
FG_YELLOW = FG_RED + FG_GREEN; (* 6 *)
FG_LIGHTGRAY = FG_RED + FG_GREEN + FG_BLUE; (* 7 *)
FG_DARKGRAY = Windows.FOREGROUND_INTENSITY; (* 8 *)
FG_BRIGHTBLUE = FG_BLUE + FG_DARKGRAY; (* 9 *)
FG_BRIGHTGREEN = FG_GREEN + FG_DARKGRAY; (* 10 *)
FG_BRIGHTCYAN = FG_CYAN + FG_DARKGRAY; (* 11 *)
FG_BRIGHTRED = FG_RED + FG_DARKGRAY; (* 12 *)
FG_BRIGHTPINK = FG_PINK + FG_DARKGRAY; (* 13 *)
FG_BRIGHTYELLOW = FG_YELLOW + FG_DARKGRAY; (* 14 *)
FG_WHITE = FG_LIGHTGRAY + FG_DARKGRAY; (* 15 *)
BG_BLACK = ATTRIBUTE{}; (* 0 *)
BG_BLUE = Windows.BACKGROUND_BLUE; (* 1 *)
BG_GREEN = Windows.BACKGROUND_GREEN; (* 2 *)
BG_CYAN = BG_BLUE + BG_GREEN; (* 3 *)
BG_RED = Windows.BACKGROUND_RED; (* 4 *)
BG_PINK = BG_RED + BG_BLUE; (* 5 *)
BG_YELLOW = BG_RED + BG_GREEN; (* 6 *)
BG_LIGHTGRAY = BG_RED + BG_GREEN + BG_BLUE; (* 7 *)
BG_DARKGRAY = Windows.BACKGROUND_INTENSITY; (* 8 *)
BG_BRIGHTBLUE = BG_BLUE + BG_DARKGRAY; (* 9 *)
BG_BRIGHTGREEN = BG_GREEN + BG_DARKGRAY; (* 10 *)
BG_BRIGHTCYAN = BG_CYAN + BG_DARKGRAY; (* 11 *)
BG_BRIGHTRED = BG_RED + BG_DARKGRAY; (* 12 *)
BG_BRIGHTPINK = BG_PINK + BG_DARKGRAY; (* 13 *)
BG_BRIGHTYELLOW = BG_YELLOW + BG_DARKGRAY; (* 14 *)
BG_WHITE = BG_LIGHTGRAY + BG_DARKGRAY; (* 15 *)
(* cursor stuff *)
PROCEDURE SetCursorPosition(x,y: CARDINAL);
PROCEDURE GetCursorPosition(VAR x,y: CARDINAL);
PROCEDURE SetCursorVisibility(visible: BOOLEAN);
(* output stuff *)
PROCEDURE GetConsoleSize(VAR x,y: CARDINAL);
PROCEDURE ClearScreen(attr: ATTRIBUTE);
PROCEDURE SetAttribute(attr: ATTRIBUTE);
PROCEDURE GetAttribute() : ATTRIBUTE;
PROCEDURE OutString(str: ARRAY OF CHAR);
(* read keys *)
PROCEDURE ReadEvent(VAR ev: EVENT);
PROCEDURE PeekEvent(VAR ev: EVENT) : BOOLEAN;
PROCEDURE GetEventCount(): CARDINAL;
PROCEDURE FlushEvents;
(* event handling *)
CONST
NO_EVENT = 0;
KEY_EVENT = Windows.KEY_EVENT;
MOUSE_EVENT = Windows.MOUSE_EVENT;
PROCEDURE EventType(ev: EVENT) : CARDINAL;
PROCEDURE GetKeyInfo(ev: EVENT; VAR pressed: BOOLEAN; VAR vk, scan: CARDINAL; VAR ch: CHAR) : BOOLEAN;
PROCEDURE GetKeyModifiers(ev: EVENT; VAR shift, ctrl, alt: BOOLEAN) : BOOLEAN;
PROCEDURE GetMouseInfo(ev: EVENT; VAR x,y: CARDINAL; VAR lb, rb: BOOLEAN) : BOOLEAN;
END Console.
<* +m2extensions *>
IMPLEMENTATION MODULE Console;
IMPORT SYSTEM, Windows, Strings;
(*FROM Storage IMPORT ALLOCATE, DEALLOCATE;*)
PROCEDURE ConsoleHandle(): Windows.HANDLE;
BEGIN
RETURN Windows.GetStdHandle(Windows.STD_OUTPUT_HANDLE);
END ConsoleHandle;
PROCEDURE ConsoleInputHandle(): Windows.HANDLE;
BEGIN
RETURN Windows.GetStdHandle(Windows.STD_INPUT_HANDLE);
END ConsoleInputHandle;
PROCEDURE SetupConsoleInput();
BEGIN
Windows.SetConsoleMode(ConsoleInputHandle(),
Windows.ENABLE_PROCESSED_INPUT +
Windows.ENABLE_LINE_INPUT +
Windows.ENABLE_ECHO_INPUT +
Windows.ENABLE_MOUSE_INPUT);
END SetupConsoleInput;
CONST
NOBUTTON = Windows.BUTTONSTATE_SET{};
LBUTTON = Windows.FROM_LEFT_1ST_BUTTON_PRESSED;
RBUTTON = Windows.RIGHTMOST_BUTTON_PRESSED;
(*************************************************************************)
PROCEDURE SetCursorPosition(x,y: CARDINAL);
VAR pos: Windows.COORD;
BEGIN
pos.X := x;
pos.Y := y;
Windows.SetConsoleCursorPosition(ConsoleHandle(), pos);
END SetCursorPosition;
PROCEDURE GetCursorPosition(VAR x,y: CARDINAL);
VAR csbi: Windows.CONSOLE_SCREEN_BUFFER_INFO;
BEGIN
Windows.GetConsoleScreenBufferInfo(ConsoleHandle(), csbi);
x := csbi.dwCursorPosition.X;
y := csbi.dwCursorPosition.Y;
END GetCursorPosition;
PROCEDURE SetCursorVisibility(visible: BOOLEAN);
VAR cci: Windows.CONSOLE_CURSOR_INFO;
BEGIN
Windows.GetConsoleCursorInfo(ConsoleHandle(), cci);
cci.bVisible := visible;
Windows.SetConsoleCursorInfo(ConsoleHandle(), cci);
END SetCursorVisibility;
PROCEDURE GetConsoleSize(VAR x,y: CARDINAL);
VAR csbi: Windows.CONSOLE_SCREEN_BUFFER_INFO;
BEGIN
Windows.GetConsoleScreenBufferInfo(ConsoleHandle(), csbi);
x := csbi.srWindow.Right - csbi.srWindow.Left + 1;
y := csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
END GetConsoleSize;
PROCEDURE ClearScreen(attr: ATTRIBUTE);
VAR w, h: CARDINAL;
coord: Windows.COORD;
foo: CARDINAL;
BEGIN
GetConsoleSize(w, h);
coord.X := 0;
coord.Y := 0;
Windows.FillConsoleOutputAttribute(ConsoleHandle(), attr, w*h, coord, foo);
Windows.FillConsoleOutputCharacter(ConsoleHandle(), ' ', w*h, coord, foo);
SetCursorPosition(0,0);
END ClearScreen;
PROCEDURE SetAttribute(attr: ATTRIBUTE);
BEGIN
Windows.SetConsoleTextAttribute(ConsoleHandle(), attr);
END SetAttribute;
PROCEDURE GetAttribute() : ATTRIBUTE;
VAR csbi: Windows.CONSOLE_SCREEN_BUFFER_INFO;
BEGIN
Windows.GetConsoleScreenBufferInfo(ConsoleHandle(), csbi);
RETURN csbi.wAttributes;
END GetAttribute;
PROCEDURE OutString(str: ARRAY OF CHAR);
VAR len, foo: CARDINAL;
BEGIN
len := Strings.Length(str);
Windows.WriteConsole(ConsoleHandle(), str, len, foo, NIL);
END OutString;
PROCEDURE ReadEvent(VAR ev: EVENT);
VAR count: CARDINAL;
BEGIN
SetupConsoleInput();
ev.EventType := 0;
Windows.ReadConsoleInput(ConsoleInputHandle(), ev, 1, count);
END ReadEvent;
PROCEDURE PeekEvent(VAR ev: EVENT) : BOOLEAN;
VAR count: CARDINAL;
BEGIN
SetupConsoleInput();
Windows.PeekConsoleInput(ConsoleInputHandle(), ev, 1, count);
RETURN count = 1;
END PeekEvent;
PROCEDURE GetEventCount(): CARDINAL;
VAR n: CARDINAL;
BEGIN
Windows.GetNumberOfConsoleInputEvents(ConsoleHandle(), n);
RETURN n;
END GetEventCount;
PROCEDURE FlushEvents;
BEGIN
Windows.FlushConsoleInputBuffer(ConsoleInputHandle());
END FlushEvents;
PROCEDURE EventType(ev: EVENT) : CARDINAL;
BEGIN
RETURN ev.EventType;
END EventType;
PROCEDURE GetMouseInfo(ev: EVENT; VAR x,y: CARDINAL; VAR lb, rb: BOOLEAN) : BOOLEAN;
BEGIN
IF EventType(ev) # MOUSE_EVENT THEN RETURN FALSE END;
x := ev.Event.MouseEvent.dwMousePosition.X;
y := ev.Event.MouseEvent.dwMousePosition.Y;
lb := (LBUTTON * ev.Event.MouseEvent.dwButtonState) # NOBUTTON;
rb := (RBUTTON * ev.Event.MouseEvent.dwButtonState) # NOBUTTON;
RETURN TRUE;
END GetMouseInfo;
PROCEDURE GetKeyInfo(ev: EVENT; VAR pressed: BOOLEAN; VAR vk, scan: CARDINAL; VAR ch: CHAR) : BOOLEAN;
BEGIN
IF EventType(ev) # KEY_EVENT THEN RETURN FALSE END;
pressed := ev.Event.KeyEvent.bKeyDown;
vk := ev.Event.KeyEvent.wVirtualKeyCode;
scan := ev.Event.KeyEvent.wVirtualScanCode;
ch := ev.Event.KeyEvent.uChar.AsciiChar;
RETURN TRUE;
END GetKeyInfo;
PROCEDURE GetKeyModifiers(ev: EVENT; VAR shift, ctrl, alt: BOOLEAN) : BOOLEAN;
BEGIN
IF EventType(ev) # KEY_EVENT THEN RETURN FALSE END;
alt := (ev.Event.KeyEvent.dwControlKeyState *
(Windows.RIGHT_ALT_PRESSED + Windows.LEFT_ALT_PRESSED) # Windows.CONTROLKEYSTATE_SET{});
ctrl := (ev.Event.KeyEvent.dwControlKeyState *
(Windows.RIGHT_CTRL_PRESSED + Windows.LEFT_CTRL_PRESSED) # Windows.CONTROLKEYSTATE_SET{});
shift := (ev.Event.KeyEvent.dwControlKeyState *
(Windows.SHIFT_PRESSED) # Windows.CONTROLKEYSTATE_SET{});
RETURN TRUE;
END GetKeyModifiers;
END Console.
<* +m2extensions *>
MODULE star;
IMPORT con:=Console;
FROM Windows IMPORT Sleep;
TYPE Direction = (UP, DOWN, LEFT, RIGHT);
CONST
VK_LEFT = 37;
VK_UP = 38;
VK_RIGHT = 39;
VK_DOWN = 40;
VK_ESC = 27;
VAR x,y, vk, foo, w, h:CARDINAL;
ev: con.EVENT;
keydown: BOOLEAN;
ch: CHAR;
dir: Direction;
PROCEDURE ClearStar;
BEGIN
con.SetCursorPosition(x, y);
con.SetAttribute(con.BG_BLUE);
con.OutString(" ");
END ClearStar;
PROCEDURE DrawStar;
BEGIN
con.SetCursorPosition(x, y);
con.SetAttribute(con.BG_BLUE + con.FG_BRIGHTYELLOW);
con.OutString("*");
END DrawStar;
PROCEDURE MoveStar;
BEGIN
CASE dir OF
| UP: IF y > 0 THEN DEC(y); ELSE y := h-1; END;
| DOWN: IF y < h-1 THEN INC(y); ELSE y := 0; END;
| LEFT: IF x > 0 THEN DEC(x); ELSE x := w-1; END;
| RIGHT: IF x < w-1 THEN INC(x); ELSE x := 0; END;
END;
END MoveStar;
BEGIN
con.ClearScreen(con.BG_BLUE);
con.GetConsoleSize(w, h);
x := w DIV 2;
y := h DIV 2;
dir := RIGHT;
con.FlushEvents();
LOOP
IF con.PeekEvent(ev) THEN
con.ReadEvent(ev);
IF con.GetKeyInfo(ev, keydown, vk, foo, ch) AND keydown THEN
CASE vk OF
| VK_DOWN: dir := DOWN;
| VK_UP: dir := UP;
| VK_LEFT: dir := LEFT;
| VK_RIGHT: dir := RIGHT;
| VK_ESC: EXIT;
END;
END;
END;
Sleep(50);
ClearStar;
MoveStar;
DrawStar;
END;
END star.
<* +m2extensions *>
MODULE test;
IMPORT con:=Console;
FROM Printf IMPORT printf;
VAR x,y, vk, scan:CARDINAL;
ev: con.EVENT;
lb, rb, keydown, ctrl, shift, alt: BOOLEAN;
ch: CHAR;
BEGIN
con.ClearScreen(con.BG_BLUE);
con.GetConsoleSize(x,y);
con.SetAttribute(con.BG_BLUE + con.FG_WHITE);
printf("Console size %d %d\n", x, y);
con.SetAttribute(con.BG_BRIGHTPINK + con.FG_BRIGHTYELLOW);
con.SetCursorPosition(30, 10);
con.OutString("Hi There!");
con.SetAttribute(con.BG_BLUE + con.FG_LIGHTGRAY);
con.SetCursorPosition(30, 11);
con.OutString("Press keys and move mouse. Escape To Exit!");
con.SetCursorVisibility(FALSE);
con.FlushEvents();
LOOP
con.ReadEvent(ev);
IF con.GetKeyInfo(ev, keydown, vk, scan, ch) THEN
con.SetCursorPosition(0, 18);
con.SetAttribute(con.BG_BLACK + con.FG_BRIGHTYELLOW);
printf("Key vk %4d scan %4d char ORD(%3d)=%c", vk, scan, ORD(ch), ch);
con.SetCursorPosition(39, 18);
IF keydown THEN
printf("DOWN!");
ELSE
printf("UP! ");
END;
IF con.GetKeyModifiers(ev, shift, ctrl, alt) THEN
con.SetCursorPosition(45, 18);
IF shift THEN printf("SHIFT "); ELSE printf("shift "); END;
IF alt THEN printf("ALT "); ELSE printf("alt "); END;
IF ctrl THEN printf("CTRL "); ELSE printf("ctrl "); END;
END;
(* handle esc *)
IF vk = 27 THEN EXIT END;
ELSIF con.GetMouseInfo(ev, x, y, lb, rb) THEN
con.SetCursorPosition(0, 20);
con.SetAttribute(con.BG_BLUE + con.FG_BRIGHTGREEN);
printf("Mouse (%2d,%2d) leftbutton %d rightbutton %d", x, y, lb, rb);
END;
END;
con.SetCursorVisibility(TRUE);
con.SetCursorPosition(0, 15);
con.SetAttribute(con.BG_BLUE + con.FG_BRIGHTRED);
END test.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment