Unit NDC;

(*
 * Jonathan R. Senning
 * Shepherd College
 * April 28, 1993
 *
 * This package is based entirely on the description of SRGP, the Simple
 * Raster Graphics Package, in "Computer Graphics: Principles and Practice",
 * Second Edition, by Foley, van Dam, Feiner, Hughes.  Addison-Wesley, 1990.
 *
 * This Turbo Pascal 6.0 Unit implements many of the SRGP routines using
 * the Turbo Pascal Graph Unit.  The only major change from the SRGP
 * description is the use of a NORMALIZED DEVICE COORDINATE SYSTEM, thus
 * the name change of the procedures from SRGP_xxxx to NDC_xxxx.
 *
 * An effort has been made to make this somewhat portable in that all the
 * Turbo Pascal Graph procedures and functions are encapsulated in
 * procedures with names beginning with Intr_.  However, there are many
 * other Turboisms in the Pascal and I expect that porting this to a
 * non-Turbo environment would involve some major hacking.
 *
 * A mouse is required to use this package.
 *)

(*=========================================================================*)
(*                           INTERFACE SECTION                             *)
(*=========================================================================*)

Interface

Uses
    Crt, Graph;

Const
    NDC_VERSION	= 'NDC Version 0.81';
    BGI_DIR	= 'C:/TP/BGI';	{Where the BGI files live}

    MAX_VERTEX	= 256;		{Maximum vertices in polygon}
    INDEFINITE	=  -1;		{Indefinite wait flag for NDC_WaitEvent}

    CONTINUOUS	= SolidLn;	{Use some of Borland's Constants}
    DASHED	= DashedLn;
    DOTTED	= DottedLn;

    HORIZONTAL	= HorizDir;
    VERTICAL	= VertDir;

    SOLID_BIT_PATTERN		=  1;
    MEDIUM_GRAY_BIT_PATTERN	=  2;
    DIAGONAL_BIT_PATTERN	=  3;
    CROSS_BIT_PATTERN		=  4;
    BRICK_BIT_PATTERN		=  5;
    MAX_BIT_PATTERNS		= 64;

    BLACK		=  0;	(* Dark colors *)
    BLUE		=  1;
    GREEN		=  2;
    CYAN		=  3;
    RED			=  4;
    MAGENTA		=  5;
    BROWN		=  6;
    LIGHT_GRAY		=  7;
    DARK_GRAY		=  8;	(* Light colors *)
    LIGHT_BLUE		=  9;
    LIGHT_GREEN 	= 10;
    LIGHT_CYAN		= 11;
    LIGHT_RED		= 12;
    LIGHT_MAGENTA	= 13;
    YELLOW		= 14;
    WHITE		= 15;

    EmptySet	= [];

Type
    Coordinate		= Real;

    DeviceType		= (KEYBOARD, LOCATOR, NO_DEVICE);
    ModeType		= (INACTIVE, SAMPLE, EVENT);
    EchoModeType	= (CURSOR, RUBBER_LINE, RUBBER_RECT, RUBBER_CROSS);
    WriteModeType	= (WRITE_REPLACE, WRITE_XOR);
    KeyboardModeType	= (RAW, EDIT);
    ButtonChordType	= (UP, DOWN);
    ButtonType		= (LEFT_BUTTON, RIGHT_BUTTON, NO_BUTTON);
    FillModeType	= (SOLID, BITMAP_PATTERN_OPAQUE);
    FillPattern		= Array [1..8] of Byte;

    IntegerPoint	= Record
				X	: Integer;
				Y	: Integer;
			  End;

    Point		= Record
				X	: Coordinate;
				Y	: Coordinate;
			  End;

    RectangleType	= Record
				BottomLeft	: Point;
				TopRight	: Point;
			  End;

    LocatorButtonArray	= Array [ButtonType] of ButtonChordType;
    LocatorButtonSet	= Set of ButtonType;

    LocatorMeasure	= Record
				Position : Point;
				ButtonOfMostRecentTransition : ButtonType;
				ButtonChord : LocatorButtonArray;
			  End;

    KeyboardMeasure	= String;

    VertexCoordinateList= Array [1..MAX_VERTEX] of Coordinate;
    VertexList		= Array [1..MAX_VERTEX] of Point;
    IntegerVertexList	= Array [1..MAX_VERTEX] of IntegerPoint;


Procedure NDC_Initialize;
Procedure NDC_Begin (X, Y : Integer);
Procedure NDC_CleanUp;
Procedure NDC_End;
Procedure NDC_ClearDisplay;
Procedure NDC_SetInputMode (Device : DeviceType; Mode : ModeType);
Procedure NDC_SetKeyboardProcessingMode (Mode : KeyboardModeType);
Procedure NDC_WaitEvent (WaitTime : LongInt; Var Device : DeviceType);
Procedure NDC_GetLocator (Var Measure : LocatorMeasure);
Procedure NDC_SetLocatorMeasure (Value : Point);
Procedure NDC_GetKeyboard (Var Measure : KeyboardMeasure);
Procedure NDC_SetLocatorButtonMask (ActiveButtons : LocatorButtonSet);
Procedure NDC_SetLocatorEchoType (Value : EchoModeType);
Procedure NDC_SetLocatorRubberAnchor (Position : Point);
Procedure NDC_SetColor (Color : Integer);
Procedure NDC_GetColor (Var Color : Integer);
Procedure NDC_GetAspectRatio (Var Xasp, Yasp : Coordinate);
Procedure NDC_DefPoint (X, Y : Coordinate; Var Pt : Point);
Procedure NDC_DefRectangle (LeftX, BottomY, RightX, TopY : Coordinate;
			 Var Rect : RectangleType);
Procedure NDC_SetWriteMode (Mode : WriteModeType);
Procedure NDC_GetWriteMode (Var Mode : WriteModeType);
Procedure NDC_SetLineStyle (Value : Integer);
Procedure NDC_SetLinePattern (Value : Word);
Procedure NDC_SetLineWidth (Value : Integer);
Procedure NDC_LineCoord (X1, Y1, X2, Y2 : Coordinate);
Procedure NDC_Line (P1, P2 : Point);
Procedure NDC_PolyLineCoord (VertexCount : Integer;
			 XArray, YArray : VertexCoordinateList);
Procedure NDC_PolyLine (VertexCount : Integer; Vertices : VertexList);
Procedure NDC_MarkerCoord (X, Y : Coordinate);
Procedure NDC_Marker (Pt : Point);
Procedure NDC_PolyMarkerCoord (VertexCount : Integer;
			XArray, YArray : VertexCoordinateList);
Procedure NDC_PolyMarker (VertexCount : Integer; Vertices : VertexList);
Procedure NDC_RectangleCoord (LeftX, BottomY, RightX, TopY : Coordinate);
Procedure NDC_RectanglePt (BottomLeft, TopRight : Point);
Procedure NDC_Rectangle (Rect : RectangleType);
Procedure NDC_Polygon (VertexCount : Integer; Vertices : VertexList);
Procedure NDC_SetFillStyle (Mode : FillModeType);
Procedure NDC_SetFillBitmapPattern (PatternIndex : Integer);
Procedure NDC_LoadBitmapPattern (PatternIndex : Integer;
			Pattern : FillPattern);
Procedure NDC_SetBackgroundColor (ColorIndex : Integer);
Procedure NDC_FillRectangleCoord (LeftX, BottomY, RightX, TopY : Coordinate);
Procedure NDC_FillRectanglePt (BottomLeft, TopRight : Point);
Procedure NDC_FillRectangle (Rect : RectangleType);
Procedure NDC_FillPolygon (VertexCount : Integer; Vertices : VertexList);
Procedure NDC_TextCoord (X, Y : Coordinate; Text : String);
Procedure NDC_Text (Origin : Point; Text : String);
Procedure NDC_SetFont (Value : Integer);
Procedure NDC_SetTextSize (Value : Integer);
Procedure NDC_SetTextDirection (Value : Integer);
Procedure NDC_InquireTextExtent (Text : String;
			Var Width, Height, Descent : Coordinate);
Procedure NDC_SetMarker (Marker : Char);
Procedure NDC_SetMarkerSize (Value : Integer);
Procedure NDC_SetActivePage (Page : Integer);
Procedure NDC_SetVisualPage (Page : Integer);

(*=========================================================================*)
(*                        IMPLEMENTATION SECTION                           *)
(*=========================================================================*)

Implementation

Const
    MOUSE_MOVED		= $01;	{Constants for Mouse Driver Flags}
    L_BUTTON_PRESSED	= $02;
    L_BUTTON_RELEASED	= $04;
    R_BUTTON_PRESSED	= $08;
    R_BUTTON_RELEASED	= $10;
    BUTTON_MASKS	: Array [ButtonType] of Word = ($01, $02, $00);

    DEFAULT_MARKER	= '*';

    SolidPattern	: FillPattern =
				($FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF);
    MediumGrayPattern	: FillPattern =
				($AA, $55, $AA, $55, $AA, $55, $AA, $55);
    DiagonalPattern	: FillPattern =
				($11, $22, $44, $88, $11, $22, $44, $88);
    CrossPattern	: FillPattern =
				($99, $66, $66, $99, $99, $66, $66, $99);
    BrickPattern	: FillPattern = 
				($00, $EF, $EF, $EF, $00, $FE, $FE, $FE);

Type
    FillPatternArray	= Array [1..MAX_BIT_PATTERNS] of FillPattern;
    InputDeviceSet	= Set of DeviceType;

    EventType		= Record
			    Case Device : DeviceType of
				LOCATOR	: (LocMeasure : LocatorMeasure);
				KEYBOARD: (KeyMeasure : KeyboardMeasure);
			  End;

    EventQueuePointer	= ^EventNode;
    EventNode		= Record
			    Event	: EventType;
			    Next	: EventQueuePointer;
			  End;

    EventQueueType	= Record
			    Front	: EventQueuePointer;
			    Back	: EventQueuePointer;
			  End;

    NDC_StatusBlock	= Record
			    Version			: String;
			    EventQueue			: EventQueueType;
			    ScreenXmax			: Integer;
			    ScreenYmax			: Integer;
			    Color			: Integer;
			    BackgroundColor		: Integer;
			    WriteMode			: WriteModeType;
			    LocatorEchoType		: EchoModeType;
			    LocatorAnchor		: Point;
			    LocatorPosition		: Point;
			    InactiveDevices		: InputDeviceSet;
			    SampleModeDevices		: InputDeviceSet;
			    EventModeDevices		: InputDeviceSet;
			    ActiveLocatorButtons	: LocatorButtonSet;
			    KeyboardProcessingMode	: KeyboardModeType;
			    LineStyle			: Integer;
			    LinePattern			: Word;
			    LineWidth			: Integer;
			    Marker			: String[1];
			    MarkerSize			: Integer;
			    TextFont			: Integer;
			    TextSize			: Integer;
			    TextDirection		: Integer;
			    FillMode			: FillModeType;
			    BitmapPatternIndex		: Integer;
			    FillBitmapPattern		: FillPatternArray;
			  End;

Var
    S		: NDC_StatusBlock;
    Mouse_Freeze: Boolean;
    GraphDriver	: Integer;
    GraphMode	: Integer;
    ErrorCode	: Integer;

(*-------------------------------------------------------------------------*)
(*-------------------------------------------------------------------------*)
(*------------------ Event Queue Procedures and Functions -----------------*)
(*-------------------------------------------------------------------------*)
(*-------------------------------------------------------------------------*)

Procedure CreateEventQueue (Var Q : EventQueueType);

Begin
    Q.Front := Nil;
    Q.Back  := Nil;
End; {CreateEventQueue}

(*-------------------------------------------------------------------------*)

Function EmptyEventQueue (Q : EventQueueType) : Boolean;

Begin
    EmptyEventQueue := (Q.Front = Nil);
End; {EmptyEventQueue}

(*-------------------------------------------------------------------------*)

Procedure InsertEventQueue (E : EventType; Var Q : EventQueueType);

Var
    TempPtr : EventQueuePointer;

Begin
    New (TempPtr);
    TempPtr^.Event := E;
    TempPtr^.Next := Nil;
    If EmptyEventQueue(Q) then Begin
	Q.Front := TempPtr;
	Q.Back  := TempPtr;
    End Else Begin
	Q.Back^.Next := TempPtr;
	Q.Back := Q.Back^.Next;
    End;
End; {InsertEventQueue}

(*-------------------------------------------------------------------------*)

Procedure RemoveEventQueue (Var E : EventType; Var Q : EventQueueType);

Var
    TempPtr : EventQueuePointer;

Begin
    If not EmptyEventQueue(Q) then Begin
	E := Q.Front^.Event;
	TempPtr := Q.Front;
	Q.Front := Q.Front^.Next;
	Dispose (TempPtr);
    End;
End; {RemoveEventQueue}

(*-------------------------------------------------------------------------*)

Procedure PeekEventQueue (Var E : EventType; Var Q : EventQueueType);

Begin
    If not EmptyEventQueue(Q) then
	E := Q.Front^.Event;
End; {PeekEventQueue}

(*-------------------------------------------------------------------------*)
(*-------------------------------------------------------------------------*)
(*---------------------------- Mouse Procedures ---------------------------*)
(*-------------------------------------------------------------------------*)
(*-------------------------------------------------------------------------*)

Procedure Mouse_On;

Begin
    Asm
	mov ax, 1h
	int 33h
    End; {Asm}
End; {Mouse_On}

(*-------------------------------------------------------------------------*)

Procedure Mouse_Off;

Begin
    Asm
	mov ax, 2h
	int 33h
    End; {Asm}
End; {Mouse_Off}

(*-------------------------------------------------------------------------*)

Procedure Mouse_StopWait;

Begin
    Mouse_Freeze := False;
End; {Mouse_StopWait}

(*-------------------------------------------------------------------------*)

Procedure Mouse_StartWait;

Begin
    Mouse_Freeze := True;
End; {Mouse_StartWait}

(*-------------------------------------------------------------------------*)

Procedure Mouse_Rubber;

Var
    X1, Y1	: Integer;
    X2, Y2	: Integer;

Begin
    If S.LocatorEchoType <> CURSOR then Begin
	SetWriteMode (XORPut);
	SetColor (LIGHT_GRAY);
	Mouse_Off;
	X1 := Round(S.LocatorAnchor.X*S.ScreenXmax);
	Y1 := Round((1.0 - S.LocatorAnchor.Y)*S.ScreenYmax);
	X2 := Round(S.LocatorPosition.X*S.ScreenXmax);
	Y2 := Round((1.0 - S.LocatorPosition.Y)*S.ScreenYmax);
	Case S.LocatorEchoType of
	    RUBBER_LINE:	Line (X1, Y1, X2, Y2);
	    RUBBER_RECT:	Rectangle (X1, Y1, X2, Y2);
	    RUBBER_CROSS:	Begin
				    Line (X1, Y1, X2, Y2);
				    SetColor (DARK_GRAY);
				    Line (0, Y2, S.ScreenXmax, Y2);
				    Line (X2, 0, X2, S.ScreenYmax);
				End; {RUBBER_CROSS}
	End; {Case}
	Mouse_On;
	Case S.WriteMode of
	    WRITE_REPLACE:	SetWriteMode (0);
	    WRITE_XOR:		SetWriteMode (1);
	End; {Case}
	SetColor (S.Color);
    End; {If}
End; {Mouse_Rubber}

(*-------------------------------------------------------------------------*)

{$S-} {Stack Checking Off}
Procedure Mouse_Handler; Far;

Const
    LEFT_BUTTON_MASK	= $01;
    RIGHT_BUTTON_MASK	= $02;

Var
    Event		: EventType;
    Mask		: Word;
    State		: Word;
    Col, Row		: Word;

Begin
    Asm
	push ds			{save original DS}
	push ax			{save AX for the momemnt}
	mov ax, seg @data	{get DS of program data}
	mov ds, ax
	pop ax			{restore AX}

	mov Mask, ax		{save condition mask}
	mov State, bx		{save button state}
	mov Col, cx		{save column position}
	mov Row, dx		{save row position}
    End; {Asm}

    Event.Device := LOCATOR;
    With Event.LocMeasure do Begin
	Position.X := Col / S.ScreenXmax;
	Position.Y := 1.0 - Row / S.ScreenYmax;

	ButtonOfMostRecentTransition := NO_BUTTON;
	If (Mask and (L_BUTTON_PRESSED or L_BUTTON_RELEASED)) <> 0 then
	    ButtonOfMostRecentTransition := LEFT_BUTTON
	Else If (Mask and (R_BUTTON_PRESSED or R_BUTTON_RELEASED)) <> 0 then
	    ButtonOfMostRecentTransition := RIGHT_BUTTON;

	If (State and LEFT_BUTTON_MASK) <> 0 then
	    ButtonChord[LEFT_BUTTON] := DOWN
	Else
	    ButtonChord[LEFT_BUTTON] := UP;

	If (State and RIGHT_BUTTON_MASK) <> 0 then
	    ButtonChord[RIGHT_BUTTON] := DOWN
	Else
	    ButtonChord[RIGHT_BUTTON] := UP;

	If ButtonOfMostRecentTransition in S.ActiveLocatorButtons then
	    InsertEventQueue (Event, S.EventQueue);

	If (not Mouse_Freeze) and ((Mask and MOUSE_MOVED) <> 0) then Begin
	    Mouse_Rubber;
	    S.LocatorPosition := Position;
	    Mouse_Rubber;
	End; {If}
    End; {With}

    Asm
	pop ds			{restore original DS}
    End; {Asm}
End; {Mouse_Handler}
{$S+} {Stack Checking On}

(*-------------------------------------------------------------------------*)

Procedure Mouse_SetHandler;

Const
    Crosshair_Mask	: Array [0..31] of Word = (
	$ffff,$ffff,$ffff,$fe3f, $fe3f,$fe3f,$fe3f,$e003,
	$e003,$e003,$fe3f,$fe3f, $fe3f,$fe3f,$ffff,$ffff,
	$0000,$0000,$0000,$0000, $0080,$0080,$0080,$0080,
	$0ff8,$0080,$0080,$0080, $0080,$0000,$0000,$0000);

Var
    Buttons	: Word;

Begin
    Buttons := MOUSE_MOVED;
    Buttons := Buttons or L_BUTTON_PRESSED or L_BUTTON_RELEASED;
    Buttons := Buttons or R_BUTTON_PRESSED or R_BUTTON_RELEASED;

    Asm
	xor ax, ax			{reset mouse driver}
	int 33h

	mov ax, cs			{code segment into AX}
	mov es, ax			{and then into ES}
	mov dx, offset Mouse_Handler	{offset of handler into DX}
	mov cx, Buttons			{mask for buttons to watch for}
	mov ax, 0Ch			{set interrupt handler}
	int 33h

	mov ax, ds			{data segment into AX}
	mov es, ax			{and then into ES}
	mov dx, offset Crosshair_Mask	{offset of mask array into DX}
	mov bx, 8			{column of cursor hot-spot}
	mov cx, 8			{row of cursor hot-spot}
	mov ax, 9h			{define graphics cursor}
	int 33h
    End; {Asm}
End; {Mouse_SetHandler}

(*-------------------------------------------------------------------------*)

Procedure Mouse_Init;

Begin
    Mouse_StopWait;
    Mouse_SetHandler;
End; {Mouse_Init}

(*-------------------------------------------------------------------------*)

Procedure Mouse_CleanUp;

Begin
    Asm
	xor ax, ax
	int 33h
    End; {Asm}
End; {Mouse_CleanUp}

(*-------------------------------------------------------------------------*)

Procedure Mouse_Status (Var ButtonMask : Word; Var Position : Point);

Var
    Col, Row	: Word;

Begin
    Asm
	mov ax, 3h
	int 33h
	mov ax, bx
	les bx, ButtonMask
	mov es:[bx], ax
	mov Col, cx
	mov Row, dx
    End; {Asm}
    Position.X := Col / S.ScreenXmax;
    Position.Y := 1.0 - Row / S.ScreenYmax;
End; {Mouse_Status}

(*-------------------------------------------------------------------------*)

Procedure Mouse_GetPosition (Var Position : Point);

Var
    Col, Row	: Word;

Begin
    Asm
	mov ax, 3h
	int 33h
	mov Col, cx
	mov Row, dx
    End; {Asm}
    Position.X := Col / S.ScreenXmax;
    Position.Y := 1.0 - Row / S.ScreenYmax;
End; {Mouse_GetPosition}

(*-------------------------------------------------------------------------*)

Procedure Mouse_SetPosition (Position : Point);

Var
    Col, Row	: Word;

Begin
    Col := Round(Position.X * S.ScreenXmax);
    Row := Round((1.0 - Position.Y) * S.ScreenYmax);
    Asm
	mov cx, Col
	mov dx, Row
	mov ax, 4h
	int 33h
    End; {Asm}
    Position.X := Col / S.ScreenXmax;
    Position.Y := 1.0 - Row / S.ScreenYmax;
End; {Mouse_SetPosition}

(*-------------------------------------------------------------------------*)
(*-------------------------------------------------------------------------*)
(*------ Interface to Turbo Pascal Graphics Procedures and Functions ------*)
(*-------------------------------------------------------------------------*)
(*-------------------------------------------------------------------------*)

Procedure Intr_Graphics_On (X, Y : Integer);

Var
    X1, Y1	: Integer;
    X2, Y2	: Integer;

Begin
    GraphDriver := VGA; {Detect;} {IBM8514;}
    GraphMode := VGAHI; {IBM8514Hi;}
    InitGraph (GraphDriver, GraphMode, BGI_DIR);
    ErrorCode := GraphResult;
    If ErrorCode <> grOK then Begin
	Writeln ('Graphics Error: ', GraphErrorMsg(ErrorCode));
	Writeln ('Program aborted...');
	Halt(1);
    End; {If}
    ClearDevice;
    X := X-1;
    Y := Y-1;
    If X > GetMaxX then
	X := GetMaxX;
    If Y > GetMaxY then
	Y := GetMaxY;
    S.ScreenXmax := X;
    S.ScreenYmax := Y;
    X1 := (GetMaxX + 1) div 2 - (X + 1) div 2;
    Y1 := (GetMaxY + 1) div 2 - (Y + 1) div 2;
    X2 := (GetMaxX + 1) div 2 + (X + 1) div 2 - 1;
    Y2 := (GetMaxY + 1) div 2 + (Y + 1) div 2 - 1;
    {SetViewPort (X1, Y1, X2, Y2, ClipOn);}
    SetViewPort (0, 0, X, Y, ClipOn);
End; {Intr_Graphics_On}

(*-------------------------------------------------------------------------*)

Procedure Intr_Graphics_Off;

Begin
    CloseGraph;
End; {Intr_Graphics_Off}

(*-------------------------------------------------------------------------*)

Procedure Intr_DrawLine (X1, Y1, X2, Y2 : Integer);

Begin
    Mouse_Off;
    Line (X1, S.ScreenYmax-Y1, X2, S.ScreenYmax-Y2);
    Mouse_On;
End; {Intr_DrawLine}

(*-------------------------------------------------------------------------*)

Procedure Intr_DrawRectangle (X1, Y1, X2, Y2 : Integer);

Begin
    Mouse_Off;
    Rectangle (X1, S.ScreenYmax-Y1, X2, S.ScreenYmax-Y2);
    Mouse_On;
End; {Intr_DrawRectangle}

(*-------------------------------------------------------------------------*)

Procedure Intr_ClearDisplay;

Begin
    Mouse_Off;
    ClearDevice;
    Mouse_On;
End; {Intr_ClearDisplay}

(*-------------------------------------------------------------------------*)

Procedure Intr_SetWriteMode (Mode : Integer);

Begin
    SetWriteMode (Mode);
End; {Intr_SetWriteMode}

(*-------------------------------------------------------------------------*)

Procedure Intr_SetColor (Color : Integer);

Begin
    SetColor (Color);
End; {Intr_SetColor}

(*-------------------------------------------------------------------------*)

Procedure Intr_SetBackgroundColor (Color : Integer);

Begin
    SetBkColor (Color);
End; {Intr_SetColor}

(*-------------------------------------------------------------------------*)

Procedure Intr_SetLineStyle (LineStyle, LinePattern, LineWidth : Integer);

Begin
    If LineWidth <= 1 then
	LineWidth := NormWidth
    Else
	LineWidth := ThickWidth;
    SetLineStyle (LineStyle, LinePattern, LineWidth);
End; {Intr_SetLineStyle}

(*-------------------------------------------------------------------------*)

Procedure Intr_SetTextReferencePoint;

Begin
    SetTextJustify (CenterText, CenterText);
End; {Intr_SetTextReferencePoint}

(*-------------------------------------------------------------------------*)

Procedure Intr_Text (X, Y : Integer; Text : String);

Begin
    Mouse_Off;
    OutTextXY (X, S.ScreenYmax-Y, Text);
    Mouse_On;
End; {Intr_Text}

(*-------------------------------------------------------------------------*)

Procedure Intr_SetTextStyle (Font : Integer; Direction : Integer;
				Size : Integer);

Begin
    SetTextStyle (Font, Direction, Size);
End; {Intr_SetTextStyle}

(*-------------------------------------------------------------------------*)

Procedure Intr_TextExtent (Var Width, Height, Descent : Integer;
				Text : String);

Begin
    Width := TextWidth (Text);
    Height := TextHeight (Text);
    If S.TextFont > 0 then
	Descent := Round(Height / 4.5)	{Empirically determined magic number}
    Else
	Descent := 0;
End; {Intr_TextExtent}

(*-------------------------------------------------------------------------*)

Procedure Intr_SetFillPattern (Pattern : FillPattern; Color : Integer);

Var
    FillBitmapPattern	: FillPatternType;
    I			: Integer;

Begin
    For I := 1 to 8 do
	FillBitmapPattern[I] := Pattern[I];
    SetFillPattern (FillBitmapPattern, Color);
End; {Intr_SetFillPattern}

(*-------------------------------------------------------------------------*)

Procedure Intr_FillPolygon (Count : Integer; List : IntegerVertexList);

Begin
    Mouse_Off;
    FillPoly (Count, List);
    Mouse_On;
End; {Intr_FillPolygon}

(*-------------------------------------------------------------------------*)

Procedure Intr_GetAspectRatio (Var Xasp, Yasp : Integer);

Var
    X, Y	: Word;

Begin
    GetAspectRatio (X, Y);
    Xasp := Integer(X);
    Yasp := Integer(Y);
End; {Intr_GetAspectRatio}

(*-------------------------------------------------------------------------*)

Procedure Intr_SetActivePage (Page : Integer);

Begin
    SetActivePage (Page);
End; {Intr_SetActivePage}

(*-------------------------------------------------------------------------*)

Procedure Intr_SetVisualPage (Page : Integer);

Begin
    SetVisualPage (Page);
End; {Intr_SetVisualPage}

(*-------------------------------------------------------------------------*)
(*-------------------------------------------------------------------------*)
(*----------------------------- NDC Procedures ----------------------------*)
(*-------------------------------------------------------------------------*)
(*-------------------------------------------------------------------------*)

Procedure NDC_Begin (X, Y : Integer);

Begin
    Intr_Graphics_On (X, Y);
    Mouse_Init;
    Mouse_GetPosition (S.LocatorPosition);
    CreateEventQueue (S.EventQueue);

    S.Version		   := NDC_VERSION;
    S.InactiveDevices      := EmptySet;
    S.SampleModeDevices    := EmptySet;
    S.EventModeDevices     := EmptySet;
    S.ActiveLocatorButtons := EmptySet;

    NDC_SetColor (WHITE);
    NDC_SetBackgroundColor (BLACK);
    NDC_SetWriteMode (WRITE_REPLACE);
    NDC_SetLocatorEchoType (CURSOR);
    NDC_SetInputMode (LOCATOR, INACTIVE);
    NDC_SetInputMode (KEYBOARD, INACTIVE);
    NDC_SetKeyboardProcessingMode (EDIT);
    NDC_SetLineStyle (CONTINUOUS);
    NDC_SetLinePattern ($FFFF);
    NDC_SetMarker (DEFAULT_MARKER);
    NDC_SetMarkerSize (1);
    NDC_SetTextSize (1);
    NDC_SetTextDirection (HORIZONTAL);
    NDC_SetFont (0);
    NDC_SetLineWidth (1);
    NDC_SetFillStyle (SOLID);
    NDC_LoadBitmapPattern (SOLID_BIT_PATTERN, SolidPattern);
    NDC_LoadBitmapPattern (MEDIUM_GRAY_BIT_PATTERN, MediumGrayPattern);
    NDC_LoadBitmapPattern (DIAGONAL_BIT_PATTERN, DiagonalPattern);
    NDC_LoadBitmapPattern (CROSS_BIT_PATTERN, CrossPattern);
    NDC_LoadBitmapPattern (BRICK_BIT_PATTERN, BrickPattern);
    NDC_SetFillBitmapPattern (SOLID_BIT_PATTERN);
End; {NDC_Begin}

(*-------------------------------------------------------------------------*)

Procedure NDC_Initialize;

Begin
    NDC_Begin (640, 480);
End; {NDC_Initialize}

(*-------------------------------------------------------------------------*)

Procedure NDC_End;

Begin
    Mouse_CleanUp;
    Intr_Graphics_Off;
End; {NDC_End}

(*-------------------------------------------------------------------------*)

Procedure NDC_CleanUp;

Begin
    NDC_End;
End; {NDC_CleanUp}

(*-------------------------------------------------------------------------*)

Procedure NDC_ClearDisplay;

Begin
    Mouse_StartWait;
    Mouse_Rubber;
    Intr_ClearDisplay;
    Mouse_Rubber;
    Mouse_StopWait;
End; {NDC_ClearDisplay}

(*-------------------------------------------------------------------------*)
(*-------------------- Interaction Handling Procedures --------------------*)
(*-------------------------------------------------------------------------*)

Procedure NDC_SetInputMode (Device : DeviceType; Mode : ModeType);

Begin
    With S do Begin
	If (Device = LOCATOR) then Begin
	    If (Device in InactiveDevices) and
			((Mode = SAMPLE) or (Mode = EVENT)) then
		Mouse_On
	    Else If (Device in (SampleModeDevices + EventModeDevices)) and
			(Mode = INACTIVE) then
		Mouse_Off;
 	End; {If}
	InactiveDevices   := InactiveDevices   - [Device];
	SampleModeDevices := SampleModeDevices - [Device];
	EventModeDevices  := EventModeDevices  - [Device];
	Case Mode of
	    INACTIVE:	InactiveDevices   := InactiveDevices   + [Device];
	    SAMPLE:	SampleModeDevices := SampleModeDevices + [Device];
	    EVENT:	EventModeDevices  := EventModeDevices  + [Device];
	End; {Case}
    End; {With}
End; {NDC_SetInputMode}

(*-------------------------------------------------------------------------*)

Procedure NDC_SetKeyboardProcessingMode (Mode : KeyboardModeType);

Begin
    S.KeyboardProcessingMode := Mode;
End; {NDC_SetKeyboardProcessingMode}

(*-------------------------------------------------------------------------*)

Procedure NDC_WaitEvent (WaitTime : LongInt; Var Device : DeviceType);

Var
    Event		: EventType;
    EventOccured	: Boolean;

Begin
    Repeat
	(*
	 * Check to see if a keyboard event has occured.  If so, then
	 * put it into the event queue.
	 *)
	If KeyPressed then Begin
	    Event.Device := KEYBOARD;
	    If S.KeyboardProcessingMode = RAW then Begin
		Event.KeyMeasure[0] := Chr(1);
		Event.KeyMeasure[1] := ReadKey;
	    End Else
		Readln (Event.KeyMeasure);
	    InsertEventQueue (Event, S.EventQueue);
	End;

	(*
	 * Check event queue.  If it is not empty then an event has
	 * occured.  However, a check must be made to insure that the
	 * event is for which event mode has been set.  If it is not,
	 * then the event is discarded.  Continue until either a valid
	 * event has occured or the event queue is empty.
	 *)
	Repeat
	    EventOccured := not EmptyEventQueue(S.EventQueue);
	    If EventOccured then Begin
		PeekEventQueue (Event, S.EventQueue);
		If not (Event.Device in S.EventModeDevices) then Begin
		    EventOccured := False;
		    RemoveEventQueue (Event, S.EventQueue);
		End;
	    End;
	Until EventOccured or EmptyEventQueue(S.EventQueue);

	(*
	 * Now either a valid event has occured or the event queue is
	 * empty.  In either case, adjust WaitTime as necessary and
	 * check the end-of-loop condition.
	 *)
	If (WaitTime > 0) then
	    WaitTime := WaitTime - 1;
    Until EventOccured or (WaitTime = 0);

    (*
     * Return either device for which event occured or NO_DEVICE which
     * indicates that no event occured (i.e., WaitEvent timed out).
     *)
    If EventOccured then
	Device := Event.Device
    Else
	Device := NO_DEVICE;
End; {NDC_WaitEvent}

(*-------------------------------------------------------------------------*)

Procedure NDC_GetLocator (Var Measure : LocatorMeasure);

(*
 * April 14
 * Does not properly handle both button press and button releases in
 * sample mode.
 *)

Var
    Event	: EventType;
    Button	: ButtonType;
    ButtonMask	: Word;

Begin
    If LOCATOR in S.EventModeDevices then Begin
	RemoveEventQueue (Event, S.EventQueue);
	Measure := Event.LocMeasure;
    End Else If LOCATOR in S.SampleModeDevices then Begin
	Mouse_Status (ButtonMask, Measure.Position);
	Measure.ButtonOfMostRecentTransition := NO_BUTTON;
	For Button := LEFT_BUTTON to RIGHT_BUTTON do
	    If (ButtonMask and BUTTON_MASKS[Button]) <> 0 then begin
		Measure.ButtonOfMostRecentTransition := Button;
		Measure.ButtonChord[Button] := DOWN;
	    End Else
		Measure.ButtonChord[Button] := UP;
    End; {Else-If}
End; {NDC_GetLocator}

(*-------------------------------------------------------------------------*)

Procedure NDC_SetLocatorMeasure (Value : Point);

Begin
    Mouse_SetPosition (Value);
End; {NDC_SetLocatorMeasure}

(*-------------------------------------------------------------------------*)

Procedure NDC_GetKeyboard (Var Measure : KeyboardMeasure);

Var
    Event	: EventType;

Begin
    If KEYBOARD in S.EventModeDevices then Begin
	RemoveEventQueue (Event, S.EventQueue);
	Measure := Event.KeyMeasure;
    End Else If KEYBOARD in S.SampleModeDevices then
	If S.KeyboardProcessingMode = RAW then Begin
	    Measure[1] := ReadKey;
	    Measure[0] := Chr(1);
	End Else
	    Readln (Measure);
End; {NDC_GetKeyboard}

(*-------------------------------------------------------------------------*)

Procedure NDC_SetLocatorButtonMask (ActiveButtons : LocatorButtonSet);

Begin
    S.ActiveLocatorButtons := ActiveButtons;
End; {NDC_SetLocatorButtonMask}

(*-------------------------------------------------------------------------*)

Procedure NDC_SetLocatorEchoType (Value : EchoModeType);

Begin
    S.LocatorEchoType := Value;
    Mouse_GetPosition (S.LocatorPosition);
    S.LocatorAnchor := S.LocatorPosition;
    Mouse_StartWait;
    Mouse_Rubber;
    Mouse_StopWait;
End; {NDC_SetLocatorEchoType}

(*-------------------------------------------------------------------------*)

Procedure NDC_SetLocatorRubberAnchor (Position : Point);

Begin
    Mouse_StartWait;
    Mouse_Rubber;
    S.LocatorAnchor := Position;
    Mouse_Rubber;
    Mouse_StopWait;
End; {NDC_SetLocatorRubberAnchor}

(*-------------------------------------------------------------------------*)
(*------------------ Color and Other Attribute Procedures -----------------*)
(*-------------------------------------------------------------------------*)

Procedure NDC_SetColor (Color : Integer);

Begin
    S.Color := Color;
    Intr_SetColor (Color);
    Case S.FillMode of
	SOLID:
	    Intr_SetFillPattern (SolidPattern, S.Color);
	BITMAP_PATTERN_OPAQUE:
	    Intr_SetFillPattern (S.FillBitmapPattern[S.BitmapPatternIndex],
					S.Color);
    End; {Case}
End; {NDC_SetColor}

(*-------------------------------------------------------------------------*)

Procedure NDC_GetColor (Var Color : Integer);

Begin
    Color := S.Color;
End; {NDC_GetColor}

(*-------------------------------------------------------------------------*)

Procedure NDC_GetAspectRatio (Var Xasp, Yasp : Coordinate);

Var
    X, Y	: Integer;

Begin
    Intr_GetAspectRatio (X, Y);
    Xasp := X;
    Yasp := Y;
End; {NDC_GetAspectRatio}

(*-------------------------------------------------------------------------*)

Procedure NDC_DefPoint (X, Y : Coordinate; Var Pt : Point);

Begin
    Pt.X := X;
    Pt.Y := Y;
End; {NDC_DefPoint}

(*-------------------------------------------------------------------------*)

Procedure NDC_DefRectangle (LeftX, BottomY, RightX, TopY : Coordinate;
				Var Rect : RectangleType);

Begin
    NDC_DefPoint (LeftX, BottomY, Rect.BottomLeft);
    NDC_DefPoint (RightX, TopY, Rect.TopRight);
End; {NDC_DefRectange}

(*-------------------------------------------------------------------------*)

Procedure NDC_SetWriteMode (Mode : WriteModeType);

Begin
    S.WriteMode := Mode;
    Case Mode of
	WRITE_REPLACE:	Intr_SetWriteMode (0);
	WRITE_XOR:	Intr_SetWriteMode (1);
    End; {Case}
End; {NDC_SetWriteMode}

(*-------------------------------------------------------------------------*)

Procedure NDC_GetWriteMode (Var Mode : WriteModeType);

Begin
    Mode := S.WriteMode;
End; {NDC_GetWriteMode}

(*-------------------------------------------------------------------------*)
(*----------------------------- Line Routines -----------------------------*)
(*-------------------------------------------------------------------------*)

Procedure NDC_SetLineStyle (Value : Integer);

Begin
    S.LineStyle := Value;
    Intr_SetLineStyle (S.LineStyle, S.LinePattern, S.LineWidth);
End; {NDC_SetLineStyle}

(*-------------------------------------------------------------------------*)

Procedure NDC_SetLinePattern (Value : Word);

Begin
    S.LinePattern := Value;
    Intr_SetLineStyle (S.LineStyle, S.LinePattern, S.LineWidth);
End; {NDC_SetLineStyle}

(*-------------------------------------------------------------------------*)

Procedure NDC_SetLineWidth (Value : Integer);

Begin
    S.LineWidth := Value;
    Intr_SetLineStyle (S.LineStyle, S.LinePattern, S.LineWidth);
End; {NDC_SetLineStyle}

(*-------------------------------------------------------------------------*)

Procedure NDC_LineCoord (X1, Y1, X2, Y2 : Coordinate);

Begin
    Mouse_StartWait;
    Mouse_Rubber;
    Intr_DrawLine (Round(X1*S.ScreenXmax), Round(Y1*S.ScreenYmax),
		Round(X2*S.ScreenXmax), Round(Y2*S.ScreenYmax));
    Mouse_Rubber;
    Mouse_StopWait;
End; {NDC_LineCoord}

(*-------------------------------------------------------------------------*)

Procedure NDC_Line (P1, P2 : Point);

Begin
    NDC_LineCoord (P1.X, P1.Y, P2.X, P2.Y);
End; {NDC_Line}

(*-------------------------------------------------------------------------*)

Procedure NDC_PolyLineCoord (VertexCount : Integer;
			      XArray, YArray : VertexCoordinateList);
Var
    I	: Integer;

Begin
    For I := 1 to VertexCount-1 do
	NDC_LineCoord (XArray[I], YArray[I], XArray[I+1], YArray[I+1]);
End; {NDC_PolyLineCoord}

(*-------------------------------------------------------------------------*)

Procedure NDC_PolyLine (VertexCount : Integer; Vertices : VertexList);

Var
    I	: Integer;

Begin
    For I := 1 to VertexCount-1 do
	NDC_Line (Vertices[I], Vertices[I+1]);
End; {NDC_PolyLine}

(*-------------------------------------------------------------------------*)
(*---------------------------- Marker Routines ----------------------------*)
(*-------------------------------------------------------------------------*)

Procedure NDC_SetMarker (Marker : Char);

Begin
    S.Marker[0] := Chr(1);
    S.Marker[1] := Marker;
End; {NDC_SetMarker}

(*-------------------------------------------------------------------------*)

Procedure NDC_SetMarkerSize (Value : Integer);

Begin
    S.MarkerSize := Value;
End; {NDC_SetMarkerSize}

(*-------------------------------------------------------------------------*)

Procedure NDC_MarkerCoord (X, Y : Coordinate);

Begin
    Intr_SetTextStyle (S.TextFont, S.TextDirection, S.MarkerSize);
    NDC_TextCoord (X, Y, S.Marker);
    Intr_SetTextStyle (S.TextFont, S.TextDirection, S.TextSize);
End; {NDC_MarkerCoord}

(*-------------------------------------------------------------------------*)

Procedure NDC_Marker (Pt : Point);

Begin
    Intr_SetTextStyle (S.TextFont, S.TextDirection, S.MarkerSize);
    NDC_Text (Pt, S.Marker);
    Intr_SetTextStyle (S.TextFont, S.TextDirection, S.TextSize);
End; {NDC_Marker}

(*-------------------------------------------------------------------------*)

Procedure NDC_PolyMarkerCoord (VertexCount : Integer;
				XArray, YArray : VertexCoordinateList);
Var
    I	: Integer;

Begin
    For I := 1 to VertexCount do
	NDC_MarkerCoord (XArray[I], YArray[I]);
End; {NDC_PolyMarkerCoord}

(*-------------------------------------------------------------------------*)

Procedure NDC_PolyMarker (VertexCount : Integer; Vertices : VertexList);

Var
    I	: Integer;

Begin
    For I := 1 to VertexCount do
	NDC_Marker (Vertices[I]);
End; {NDC_PolyMarker}

(*-------------------------------------------------------------------------*)
(*-------------------- Rectangle and Polygon Routines ---------------------*)
(*-------------------------------------------------------------------------*)

Procedure NDC_RectangleCoord (LeftX, BottomY, RightX, TopY : Coordinate);

Begin
    Mouse_StartWait;
    Mouse_Rubber;
    Intr_DrawRectangle (Round(LeftX*S.ScreenXmax), Round(TopY*S.ScreenYmax),
		Round(RightX*S.ScreenXmax), Round(BottomY*S.ScreenYmax));
    Mouse_Rubber;
    Mouse_StopWait;
End; {NDC_RectangleCoord}

(*-------------------------------------------------------------------------*)

Procedure NDC_RectanglePt (BottomLeft, TopRight : Point);

Begin
    NDC_RectangleCoord (BottomLeft.X, BottomLeft.Y, TopRight.X, TopRight.Y);
End; {NDC_RectanglePt}

(*-------------------------------------------------------------------------*)

Procedure NDC_Rectangle (Rect : RectangleType);

Begin
    NDC_RectanglePt (Rect.BottomLeft, Rect.TopRight);
End; {NDC_Rectangle}

(*-------------------------------------------------------------------------*)

Procedure NDC_Polygon (VertexCount : Integer; Vertices : VertexList);

Var
    I	: Integer;

Begin
    For I := 1 to VertexCount-1 do
	NDC_Line (Vertices[I], Vertices[I+1]);
    NDC_Line (Vertices[VertexCount], Vertices[1]);
End; {NDC_Polygon}

(*-------------------------------------------------------------------------*)
(*-------------------------- Fill Area Procedures -------------------------*)
(*-------------------------------------------------------------------------*)

Procedure NDC_SetFillStyle (Mode : FillModeType);

Begin
    S.FillMode := Mode;
    Case S.FillMode of
	SOLID:
	    Intr_SetFillPattern (SolidPattern, S.Color);
	BITMAP_PATTERN_OPAQUE:
	    Intr_SetFillPattern (S.FillBitmapPattern[S.BitmapPatternIndex],
					S.Color);
    End; {Case}
End; {NDC_SetFillStyle}

(*-------------------------------------------------------------------------*)

Procedure NDC_SetFillBitmapPattern (PatternIndex : Integer);

Begin
    If PatternIndex <= MAX_BIT_PATTERNS then
	S.BitmapPatternIndex := PatternIndex
    Else
	S.BitmapPatternIndex := MAX_BIT_PATTERNS;
    If S.FillMode = BITMAP_PATTERN_OPAQUE then
	Intr_SetFillPattern (S.FillBitmapPattern[S.BitmapPatternIndex],
					S.Color);
End; {NDC_SetFillBitmapPattern}

(*-------------------------------------------------------------------------*)

Procedure NDC_LoadBitmapPattern (PatternIndex : Integer;
			Pattern : FillPattern);

Begin
    If PatternIndex <= MAX_BIT_PATTERNS then
	S.FillBitmapPattern[PatternIndex] := Pattern;
End; {NDC_LoadBitmapPattern}

(*-------------------------------------------------------------------------*)

Procedure NDC_SetBackgroundColor (ColorIndex : Integer);

Begin
    S.BackgroundColor := ColorIndex;
    Intr_SetBackgroundColor (ColorIndex);
End; {NDC_SetBackgroundColor}

(*-------------------------------------------------------------------------*)

Procedure NDC_FillRectangleCoord (LeftX, BottomY, RightX, TopY : Coordinate);

Var
    V	: IntegerVertexList;

Begin
    V[1].X := Round(LeftX*S.ScreenXmax);
    V[1].Y := Round((1.0-TopY)*S.ScreenYmax);
    V[2].X := Round(RightX*S.ScreenXmax);
    V[2].Y := Round((1.0-TopY)*S.ScreenYmax);
    V[3].X := Round(RightX*S.ScreenXmax);
    V[3].Y := Round((1.0-BottomY)*S.ScreenYmax);
    V[4].X := Round(LeftX*S.ScreenXmax);
    V[4].Y := Round((1.0-BottomY)*S.ScreenYmax);
    Mouse_StartWait;
    Mouse_Rubber;
    Intr_FillPolygon (4, V);
    Mouse_Rubber;
    Mouse_StopWait;
End; {NDC_FillRectangleCoord}

(*-------------------------------------------------------------------------*)

Procedure NDC_FillRectanglePt (BottomLeft, TopRight : Point);

Begin
    NDC_FillRectangleCoord (BottomLeft.X, BottomLeft.Y,
				TopRight.X, TopRight.Y);
End; {NDC_FillRectanglePt}

(*-------------------------------------------------------------------------*)

Procedure NDC_FillRectangle (Rect : RectangleType);

Begin
    NDC_FillRectanglePt (Rect.BottomLeft, Rect.TopRight);
End; {NDC_FillRectangle}

(*-------------------------------------------------------------------------*)

Procedure NDC_FillPolygon (VertexCount : Integer; Vertices : VertexList);

Var
    I	: Integer;
    V	: IntegerVertexList;

Begin
    For I := 1 to VertexCount do Begin
	V[I].X := Round(Vertices[I].X * S.ScreenXmax);
	V[I].Y := Round((1.0-Vertices[I].Y) * S.ScreenYmax);
    End; {For}
    Mouse_StartWait;
    Mouse_Rubber;
    Intr_FillPolygon (VertexCount, V);
    Mouse_Rubber;
    Mouse_StopWait;
End; {NDC_FillPolygon}

(*-------------------------------------------------------------------------*)
(*----------------------------- Text Routines -----------------------------*)
(*-------------------------------------------------------------------------*)

Procedure NDC_TextCoord (X, Y : Coordinate; Text : String);

Begin
    Intr_SetTextReferencePoint;
    Mouse_StartWait;
    Mouse_Rubber;
    Intr_Text (Round(X*S.ScreenXmax), Round(Y*S.ScreenYmax), Text);
    Mouse_Rubber;
    Mouse_StopWait;
End; {NDC_Text}

(*-------------------------------------------------------------------------*)

Procedure NDC_Text (Origin : Point; Text : String);

Begin
    Intr_SetTextReferencePoint;
    Mouse_StartWait;
    Mouse_Rubber;
    Intr_Text (Round(Origin.X*S.ScreenXmax), Round(Origin.Y*S.ScreenYmax),
			Text);
    Mouse_Rubber;
    Mouse_StopWait;
End; {NDC_Text}

(*-------------------------------------------------------------------------*)

Procedure NDC_SetFont (Value : Integer);

Begin
    S.TextFont := Value;
    Intr_SetTextStyle (S.TextFont, S.TextDirection, S.TextSize)
End; {NDC_SetFont}

(*-------------------------------------------------------------------------*)

Procedure NDC_SetTextSize (Value : Integer);

Begin
    S.TextSize := Value;
    Intr_SetTextStyle (S.TextFont, S.TextDirection, S.TextSize)
End; {NDC_SetTextSize}

(*-------------------------------------------------------------------------*)

Procedure NDC_SetTextDirection (Value : Integer);

Begin
    S.TextDirection := Value;
    Intr_SetTextStyle (S.TextFont, S.TextDirection, S.TextSize)
End; {NDC_SetTextDirection}

(*-------------------------------------------------------------------------*)

Procedure NDC_InquireTextExtent (Text : String;
				Var Width, Height, Descent : Coordinate);

Var
    W, H, D	: Integer;

Begin
    Intr_TextExtent (W, H, D, Text);
    Width := W / S.ScreenXmax;
    Height := H / S.ScreenYmax;
    Descent := D / S.ScreenYmax;
End; {NDC_InquireTextExtent}

(*-------------------------------------------------------------------------*)

Procedure NDC_SetActivePage (Page : Integer);

Begin
    Intr_SetActivePage (Page);
End; {NDC_SetActivePage}

(*-------------------------------------------------------------------------*)

Procedure NDC_SetVisualPage (Page : Integer);

Begin
    Intr_SetVisualPage (Page);
End; {NDC_SetVisualPage}

(*-------------------------------------------------------------------------*)

End. {Unit NDC}
