Metropoli BBS
VIEWER: dosgraph.c MODE: TEXT (ASCII)
/*****************************************************************************
*   "Irit" - the 3d polygonal solid modeller.				     *
*									     *
* Written by:  Gershon Elber		               Ver 0.1, Mar. 1990    *
******************************************************************************
* MSDOS graphical interface for IRIT. Based on intr_lib windowing library.   *
*****************************************************************************/

#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifndef DJGCC
#include <conio.h>
#endif /* DJGCC */
#include "graphgen.h"
#include "intr_lib.h"
#include "intr_gr.h"

int ViewWindowID, InputWindowID, StatusWindowID, TransWindowID;

#ifdef DJGCC
#define NUM_OF_TEXT_LINES 200
#else
#define NUM_OF_TEXT_LINES 50
#endif /* DJGCC */

/* Interactive menu setup structure: */
#define INTERACT_NUM_OF_STRINGS		3
#define INTERACT_NUM_OF_SUB_WNDWS_FULL	16
#define INTERACT_NUM_OF_SUB_WNDWS_PART	13
#define INTERACT_SUB_WINDOW_HEIGHT	0.04  /* Actually half Height/Width. */
#define INTERACT_SUB_WINDOW_WIDTH	0.8
#define INTERACT_X_CENTER		((SW_MAX_X + SW_MIN_X) / 2.0 + 0.02)

typedef struct InteractString {
    IntrRType X, Y;
    int Color;
    char *Str;
} InteractString;

typedef struct InteractSubWindow {
    IntrRType X, Y;					   /* Center points. */
    GraphicEventType InteractCode;
    int Color,
	TextInside; /* If TRUE, Str will be in window, otherwise left to it. */
    char *Str;
} InteractSubWindow;

typedef struct InteractWindowStruct {	 /* The interactive menu structures. */
    /* Rotate, Translate, Scale strings: */
    InteractString Strings[INTERACT_NUM_OF_STRINGS];
    InteractSubWindow SubWindows[INTERACT_NUM_OF_SUB_WNDWS_FULL];
} InteractWindowStruct;

static IntrBType
    HasStatusWindow = FALSE,
    HasInputWindow = FALSE;

static int
    InteractNumOfSubWndws = INTERACT_NUM_OF_SUB_WNDWS_FULL;
    
/* Interactive mode menu set up structure is define below: */
static InteractWindowStruct InteractMenuFull = {
    { { 0.0, -0.60, RED,   "Rotate" },
      { 0.0, -0.28, GREEN, "Translate" },
      { 0.0,  0.04, CYAN,  "Scale" },
    },
    { { 0.0, -0.9,  EVENT_SCR_OBJ_TGL,    CYAN,  TRUE,  "Screen Coords." },
      { 0.0, -0.78, EVENT_PERS_ORTHO_TGL, BLUE,   TRUE,  "Perspectiv" },
      { 0.0, -0.7,  EVENT_PERS_ORTHO_Z,   BLUE,   FALSE, "Z" },
      { 0.0, -0.54, EVENT_ROTATE_X,       RED,    FALSE, "X" }, /* Rot */
      { 0.0, -0.46, EVENT_ROTATE_Y,       RED,    FALSE, "Y" },
      { 0.0, -0.38, EVENT_ROTATE_Z,       RED,    FALSE, "Z" },
      { 0.0, -0.22, EVENT_TRANSLATE_X,    GREEN,  FALSE, "X" }, /* Trans */
      { 0.0, -0.14, EVENT_TRANSLATE_Y,    GREEN,  FALSE, "Y" },
      { 0.0, -0.06, EVENT_TRANSLATE_Z,    GREEN,  FALSE, "Z" },
      { 0.0,  0.1,  EVENT_SCALE,          CYAN,   FALSE, "" },  /* Scale */
      { 0.0,  0.26, EVENT_DEPTH_CUE,      MAGENTA,TRUE,  "Depth cue" },
      { 0.0,  0.42, EVENT_SAVE_GIF,       YELLOW, TRUE,  "Save GIF" },
      { 0.0,  0.5,  EVENT_SAVE_PS,        YELLOW, TRUE,  "Save PS" },
      { 0.0,  0.62, EVENT_SAVE_MATRIX,    YELLOW, TRUE,  "Save Matrix" },
      { 0.0,  0.7,  EVENT_RESET_MATRIX,   YELLOW, TRUE,  "Reset Matrix" },
      { 0.0,  0.85, EVENT_QUIT,           WHITE,  TRUE,  "Quit" },
    }
};
static InteractWindowStruct InteractMenuPartial = {
    { { 0.0, -0.60, RED,   "Rotate" },
      { 0.0, -0.28, GREEN, "Translate" },
      { 0.0,  0.04, CYAN,  "Scale" },
    },
    { { 0.0, -0.9,  EVENT_SCR_OBJ_TGL,    CYAN,  TRUE,  "Screen Coords." },
      { 0.0, -0.78, EVENT_PERS_ORTHO_TGL, BLUE,   TRUE,  "Perspectiv" },
      { 0.0, -0.7,  EVENT_PERS_ORTHO_Z,   BLUE,   FALSE, "Z" },
      { 0.0, -0.54, EVENT_ROTATE_X,       RED,    FALSE, "X" }, /* Rot */
      { 0.0, -0.46, EVENT_ROTATE_Y,       RED,    FALSE, "Y" },
      { 0.0, -0.38, EVENT_ROTATE_Z,       RED,    FALSE, "Z" },
      { 0.0, -0.22, EVENT_TRANSLATE_X,    GREEN,  FALSE, "X" }, /* Trans */
      { 0.0, -0.14, EVENT_TRANSLATE_Y,    GREEN,  FALSE, "Y" },
      { 0.0, -0.06, EVENT_TRANSLATE_Z,    GREEN,  FALSE, "Z" },
      { 0.0,  0.1,  EVENT_SCALE,          CYAN,   FALSE, "" },  /* Scale */
      { 0.0,  0.26, EVENT_DEPTH_CUE,      MAGENTA,TRUE,  "Depth cue" },
      { 0.0,  0.42, EVENT_RESET_MATRIX,   YELLOW, TRUE,  "Reset Matrix" },
      { 0.0,  0.58, EVENT_QUIT,           WHITE,  TRUE,  "Quit" },
    }
};
static InteractWindowStruct *InteractMenu = &InteractMenuFull;
	
static IntrPopUpMenuStruct *PUWndwMenu;
static char *PopUpMenuStrs[] = {
    "Redraw All",
    "Move",
    "Resize",
    "Pop",
    "Push",
    "Zoom",
    "Reset",
    "Headers",
};
#define POP_UP_MENU_SIZE (sizeof(PopUpMenuStrs) / sizeof(char *))

static void SetViewWindowFBBox(int WindowID);
static IntrEventType LclGetChar(int *x, int *y);
static void SetBBoxSize(IntrBBoxStruct *BBox, char *GlblTextWindowPos);
static void TransWndwRefreshFunction(int WindowID);
static void TransWndwRefreshFunctionAux(void);
static void StatusWndwRefreshFunction(int WindowID);
static void InteractUpdateMenu(char *Str, int Entry);
static void InputWndwRefreshFunction(int WindowID);
static void SetMaximumBBoxSize(int WindowID);
static void PopUpMenuFunc(int KeyStroke);

/******************************************************************************
* A simple test for the Intr_lib library.				      *
******************************************************************************/
void GGInitIntrLibWindows(int GraphDriver, int FullTransMode)
{
    IntrCursorShapeStruct Cursor;
    IntrBBoxStruct BBox;
    IntrFBBoxStruct FBBox;

    IntrSetSaveBackPath(GlblIntrSaveDisk);
    IntrSetSaveBackMethod(GlblIntrSaveMethod);
    IntrSetHandleInternalEvents(TRUE, FALSE);

#ifdef __MSDOS__
    GRSetDefaultDriver(GraphDriver);
#endif /* __MSDOS */

    if (FullTransMode) {
    	InteractNumOfSubWndws = INTERACT_NUM_OF_SUB_WNDWS_FULL;
	InteractMenu = &InteractMenuFull;
    }
    else {
    	InteractNumOfSubWndws = INTERACT_NUM_OF_SUB_WNDWS_PART;
	InteractMenu = &InteractMenuPartial;
    }

    IntrInit();

    IntrSetMouseSensitivity(GlblMouseSensitivity);
    IntrSetInputDevice((GlblMouseExists ? INTR_INPT_DEVICE_MOUSE : 0) |
		       (GlblJoystickExists ? INTR_INPT_DEVICE_JOYSTICK : 0) |
		       INTR_INPT_DEVICE_KEYBOARD);

    IntrRegisterKeyStroke(0x13B /* F1 */, PopUpMenuFunc);

    /* Set the default cursor to arrow. */
    Cursor.CursorType = INTR_CURSOR_ARROW;
    IntrSetCursorType(&Cursor);

    /* Prepare the pop up menu. */
    PUWndwMenu = IntrPopUpMenuCreate("Windows", PopUpMenuStrs, 0,
				  POP_UP_MENU_SIZE,
				  INTR_COLOR_GREEN, INTR_COLOR_CYAN,
				  INTR_COLOR_YELLOW, INTR_COLOR_MAGENTA,
                                  16, &Cursor);

    SetBBoxSize(&BBox, GlblViewWndwPos);
    ViewWindowID = IntrWndwCreate("View",
				  GlblWindowFrameWidth,
				  &BBox,
				  GlblViewFrameColor,
				  GlblViewBackColor,
				  &Cursor,
				  NULL,
				  NULL);
    IntrWndwSetDrawHeader(ViewWindowID, GlblDrawHeader);
    IntrWndwPop(ViewWindowID, TRUE, FALSE);
    SetViewWindowFBBox(ViewWindowID);
    
    SetBBoxSize(&BBox, GlblTransWndwPos);
    TransWindowID = IntrWndwCreate("Transformations",
				   GlblWindowFrameWidth,
				   &BBox,
				   GlblTransFrameColor,
				   GlblTransBackColor,
				   &Cursor,
				   NULL,
				   TransWndwRefreshFunction);
    FBBox.FXmin = FBBox.FYmin = -1.0;
    FBBox.FXmax = FBBox.FYmax =  1.0;
    if (!FullTransMode) FBBox.FYmax =  0.7;
    IntrWndwSetFBBox(TransWindowID, &FBBox);
    IntrWndwSetDrawHeader(TransWindowID, GlblDrawHeader);
    IntrWndwPop(TransWindowID, TRUE, TRUE);

    if (HasStatusWindow) {
	SetBBoxSize(&BBox, GlblStatusWndwPos);
	StatusWindowID = IntrWndwCreate("Status",
					GlblWindowFrameWidth,
					&BBox,
					GlblStatusFrameColor,
					GlblStatusBackColor,
					&Cursor,
					NULL,
					StatusWndwRefreshFunction);
	IntrWndwSetDrawHeader(StatusWindowID, GlblDrawHeader);
	IntrWndwPop(StatusWindowID, TRUE, TRUE);
    }

    if (HasInputWindow) {
	SetBBoxSize(&BBox, GlblInputWndwPos);
	InputWindowID = IntrWndwCreate("Input",
				       GlblWindowFrameWidth,
				       &BBox,
				       GlblInputFrameColor,
				       GlblInputBackColor,
				       &Cursor,
				       NULL,
				       InputWndwRefreshFunction);
	IntrTextInitWindow(InputWindowID, TRUE, INTR_COLOR_YELLOW,
			   INTR_COLOR_RED, INTR_SCRLBAR_NONE,
			   INTR_SCRLBAR_LEFT, NUM_OF_TEXT_LINES, 90);
	IntrWndwSetDrawHeader(InputWindowID, GlblDrawHeader);
	IntrTextSetSmoothScroll(GlblSmoothTextScroll);
	IntrWndwPop(InputWindowID, TRUE, TRUE);
    }

    /* Make the get line intr_lib routine use this routine to get chars. */
    GRSetGetKeyFunc(LclGetChar);
}

/******************************************************************************
* A function bounded to a quit key.					      *
******************************************************************************/
void GGClosIntrLibWindows(void)
{
    IntrPopUpMenuDelete(PUWndwMenu);
    IntrWndwDelete(ViewWindowID, FALSE);
    IntrWndwDelete(TransWindowID, FALSE);
    if (HasStatusWindow)
	IntrWndwDelete(StatusWindowID, FALSE);
    if (HasInputWindow)
	IntrWndwDelete(InputWindowID, FALSE);

    IntrClose();
}

/******************************************************************************
* Wait for events. Basically waits for an event in the Transformation (Menu)  *
* window and returns its interaction code.		                      *
******************************************************************************/
GraphicEventType GGGetGraphicEvent(RealType *ChangeFactor)
{
    int i, x, y;
    GraphicEventType InteractCode;

    while (TRUE) {
	IntrRType Wx, Wy;

	switch (IntrGetEventWait(&x, &y)) {
	    case INTR_EVNT_SELECT:
		if (IntrMapEventToRWindow(TransWindowID, x, y, &Wx, &Wy)) {
		    if (Wx < -INTERACT_SUB_WINDOW_WIDTH ||
			Wx > INTERACT_SUB_WINDOW_WIDTH)
			break;
		    for (i = 0; i < InteractNumOfSubWndws; i++)
			if (Wy < InteractMenu -> SubWindows[i].Y +
						INTERACT_SUB_WINDOW_HEIGHT &&
			    Wy > InteractMenu -> SubWindows[i].Y -
						INTERACT_SUB_WINDOW_HEIGHT) {
			    InteractCode = InteractMenu -> SubWindows[i].InteractCode;

			    switch (InteractCode) {
				case EVENT_SCR_OBJ_TGL:
				    switch (GlblTransformMode) {
					case TRANS_SCREEN:
					    InteractUpdateMenu("Object Coords.", 0);
					    GlblTransformMode = TRANS_OBJECT;
					    break;
					case TRANS_OBJECT:
					    InteractUpdateMenu("Screen Coords.", 0);
					    GlblTransformMode = TRANS_SCREEN;
					    break;
				    }
				    break;
				case EVENT_PERS_ORTHO_TGL:
				    switch (GlblViewMode) {
					case VIEW_PERSPECTIVE:
					    InteractUpdateMenu("Orthographic", 1);
					    GlblViewMode = VIEW_ORTHOGRAPHIC;
					    break;
					case VIEW_ORTHOGRAPHIC:
					    InteractUpdateMenu("Perspective", 1);
					    GlblViewMode = VIEW_PERSPECTIVE;
					    break;
				    }
				    break;
				case EVENT_DEPTH_CUE:
				    GlblDepthCue = !GlblDepthCue;
				    InteractUpdateMenu(
					GlblDepthCue ? "Depth Cue" : "No Depth Cue",
					10);
				    break;
				default:
				    break;
			    }

			    *ChangeFactor = Wx / INTERACT_SUB_WINDOW_WIDTH;
			    return InteractCode;
			}
		}
		else {
		    PopUpMenuFunc(0);               /* Pop up the main menu. */
		}
		break;
	    case INTR_EVNT_ABORT:
		break;
	}
    }
}

/******************************************************************************
* Similar to GGGetGraphicEvent above but for intr_lib get graphic line        *
* routine GGGetGraphicLine, so it may activate the pop up menu async.         *
******************************************************************************/
static IntrEventType LclGetChar(int *x, int *y)
{
    IntrRType Wx, Wy;
    IntrEventType Event;

    switch (Event = IntrGetEventWait(x, y)) {
	case INTR_EVNT_SELECT:
	    if (!IntrMapEventToRWindow(TransWindowID, *x, *y, &Wx, &Wy)) {
		PopUpMenuFunc(0);                   /* Pop up the main menu. */
	    }
	    break;
    }

    return Event;
}

/******************************************************************************
* Enables/Disables (default) the existance of Input and Status windows.       *
* This function should be called BEFORE InitIntrLibWindows above.	      *
******************************************************************************/
void GGSetStatusInputWindows(IntrBType HasStatusWndw, IntrBType HasInputWndw)
{
    HasStatusWindow = HasStatusWndw;
    HasInputWindow = HasInputWndw;
}

/*****************************************************************************
*  Routine to test if quit display event - occured - SPACE was hit on	     *
* keyboard or right button was clicked on mouse.			     *
*****************************************************************************/
int GGIsAbortKeyPressed(void)
{
    int x, y;

    return IntrGetEventNoWait(&x, &y) == INTR_EVNT_ABORT;
}

/******************************************************************************
* Parse the position string and set the BBox location.			      *
******************************************************************************/
static void SetBBoxSize(IntrBBoxStruct *BBox, char *GlblTextWindowPos)
{
    int i;
    IntrRType XYLoc[4];

    if (sscanf(GlblTextWindowPos, "%f, %f, %f, %f",
	       &XYLoc[0], &XYLoc[1], &XYLoc[2], &XYLoc[3]) != 4) {
	XYLoc[0] = XYLoc[1] = 0.1;
	XYLoc[2] = XYLoc[3] = 0.9;
    }

    for (i = 0; i < 4; i++) {
	if (XYLoc[i] < 0.0) XYLoc[i] = 0.0;
	if (XYLoc[i] > 1.0) XYLoc[i] = 1.0;
    }

    BBox -> Xmin = (int) (XYLoc[0] * GRScreenMaxX);
    BBox -> Ymin = (int) (XYLoc[1] * GRScreenMaxY);
    BBox -> Xmax = (int) (XYLoc[2] * GRScreenMaxX);
    BBox -> Ymax = (int) (XYLoc[3] * GRScreenMaxY);
}


/******************************************************************************
* A routine to compute the normalized floating bbox for the provided window.  *
******************************************************************************/
static void SetViewWindowFBBox(int WindowID)
{
    IntrBBoxStruct *BBox;
    IntrFBBoxStruct FBBox;
    
    /* Compute the aspect ratio of this window and save it so we can match   */
    /* it if the window is resized or zoomed etc.			     */
    BBox = IntrWndwGetBBox(WindowID);
    if (BBox -> _Dy > BBox -> _Dx) {
	/* Normalize the X axis to hold -1 to 1 domain. */
	FBBox.FYmin = 			      /* Note the Y axis is flipped. */
	     (1.0 / GRScreenAspect) * (((IntrRType) BBox -> _Dy) / BBox -> _Dx);
	FBBox.FYmax = -FBBox.FYmin;
	FBBox.FXmin = -1.0;
	FBBox.FXmax = 1.0;
    }
    else {
	/* Normalize the Y axis to hold -1 to 1 domain. */
	FBBox.FYmin = 1.0;		      /* Note the Y axis is flipped. */
        FBBox.FYmax = -1.0;
	FBBox.FXmax =
		     GRScreenAspect * (((IntrRType) BBox -> _Dx) / BBox -> _Dy);
	FBBox.FXmin = -FBBox.FXmax;
    }
    IntrWndwSetFBBox(WindowID, &FBBox);
}

/******************************************************************************
* A routine invoked when ever the Trans window needs to be refreshed.	      *
******************************************************************************/
static void TransWndwRefreshFunction(int WindowID)
{
    switch (GlblTransformMode) {
	case TRANS_SCREEN:
	    InteractMenu -> SubWindows[0].Str = "Screen Coords.";
	    break;
	case TRANS_OBJECT:
	    InteractMenu -> SubWindows[0].Str = "Object Coords.";
	    break;
    }

    switch (GlblViewMode) {
	case VIEW_PERSPECTIVE:
	    InteractMenu -> SubWindows[1].Str = "Perspective";
	    break;
	case VIEW_ORTHOGRAPHIC:
	    InteractMenu -> SubWindows[1].Str = "Orthographic";
	    break;
    }

    if (GlblDepthCue)
	InteractMenu -> SubWindows[10].Str = "Depth Cue";
    else
	InteractMenu -> SubWindows[10].Str = "No Depth Cue";

    TransWndwRefreshFunctionAux();	    /* Draw the transformation menu. */
}

/******************************************************************************
*  Routine to draw the Transformationnu in the Menu window, using the         *
* InteractiveMenu structure defined above.				      *
*  It is assumed that string not inside of SubWindow will be of length 1.     *
******************************************************************************/
static void TransWndwRefreshFunctionAux(void)
{
    int i;

    GRPushTextSetting();
    GRSetTextJustify(GR_TEXT_HJUSTIFY_CENTER,
		     GR_TEXT_VJUSTIFY_CENTER);	   /* Draw strings centered. */

    GRSetLineStyle(GR_SOLID_LINE, 0, GR_NORM_WIDTH);

    for (i = 0; i < INTERACT_NUM_OF_STRINGS; i++) {/* Draw strings of struct.*/
	GRSetColor(InteractMenu -> Strings[i].Color);
	IntrWndwRText(InteractMenu -> Strings[i].X,
		      InteractMenu -> Strings[i].Y,
		      InteractMenu -> Strings[i].Str);
    }

    for (i = 0; i < InteractNumOfSubWndws; i++) {
	/* Draw struct sub windows. */
	GRSetColor(InteractMenu -> SubWindows[i].Color);
	/* Draw the frame of the SubWindow: */
	IntrWndwRMoveTo(
	    InteractMenu -> SubWindows[i].X - INTERACT_SUB_WINDOW_WIDTH,
	    InteractMenu -> SubWindows[i].Y - INTERACT_SUB_WINDOW_HEIGHT);
	IntrWndwRLineTo(
	    InteractMenu -> SubWindows[i].X + INTERACT_SUB_WINDOW_WIDTH,
	    InteractMenu -> SubWindows[i].Y - INTERACT_SUB_WINDOW_HEIGHT);
	IntrWndwRLineTo(
	    InteractMenu -> SubWindows[i].X + INTERACT_SUB_WINDOW_WIDTH,
	    InteractMenu -> SubWindows[i].Y + INTERACT_SUB_WINDOW_HEIGHT);
	IntrWndwRLineTo(
	    InteractMenu -> SubWindows[i].X - INTERACT_SUB_WINDOW_WIDTH,
	    InteractMenu -> SubWindows[i].Y + INTERACT_SUB_WINDOW_HEIGHT);
	IntrWndwRLineTo(
	    InteractMenu -> SubWindows[i].X - INTERACT_SUB_WINDOW_WIDTH,
	    InteractMenu -> SubWindows[i].Y - INTERACT_SUB_WINDOW_HEIGHT);

	/* Now the strings inside (and if outside, a middle vertical line): */
	if (InteractMenu -> SubWindows[i].TextInside)
	    IntrWndwRText(InteractMenu -> SubWindows[i].X,
			  InteractMenu -> SubWindows[i].Y,
			  InteractMenu -> SubWindows[i].Str);
	else {
	    IntrWndwRText(InteractMenu -> SubWindows[i].X -
				INTERACT_SUB_WINDOW_WIDTH - 0.1,
			  InteractMenu -> SubWindows[i].Y,
			  InteractMenu -> SubWindows[i].Str);
	    IntrWndwRLine(InteractMenu -> SubWindows[i].X,
			  InteractMenu -> SubWindows[i].Y -
				INTERACT_SUB_WINDOW_HEIGHT,
			  InteractMenu -> SubWindows[i].X,
			  InteractMenu -> SubWindows[i].Y +
				INTERACT_SUB_WINDOW_HEIGHT);
	}
    }

    GRPopTextSetting();
}

/******************************************************************************
* A routine invoked when ever the Status window needs to be refreshed.	      *
******************************************************************************/
static void StatusWndwRefreshFunction(int WindowID)
{
    GRPushTextSetting();
    GRSetTextJustify(GR_TEXT_HJUSTIFY_CENTER,
		     GR_TEXT_VJUSTIFY_CENTER);	   /* Draw strings centered. */

    GRSetLineStyle(GR_SOLID_LINE, 0, GR_NORM_WIDTH);

    GGMySetColor(GREEN);
    IntrWndwRText(0.0, -0.6, "Irit");

    GGMySetColor(GREEN);
    IntrWndwRText(0.0, -0.2, VERSION);
    
    GGMySetColor(RED);
    IntrWndwRText(0.0, 0.2, "Core Left");

    GRPopTextSetting();
}

/*****************************************************************************
*  Routine to update entry Entry with a new string Str.			     *
*****************************************************************************/
static void InteractUpdateMenu(char *Str, int Entry)
{
    GRPushTextSetting();

    GRSetTextJustify(GR_TEXT_HJUSTIFY_CENTER,
		     GR_TEXT_VJUSTIFY_CENTER);	   /* Draw strings centered. */

    GRPushViewPort();
    IntrWndwPop(TransWindowID, FALSE, FALSE);
    GGViewPortTransArea();

    GRSetColor(BLACK);				    /* Erase the old string. */
    IntrWndwRText(InteractMenu -> SubWindows[Entry].X,
		  InteractMenu -> SubWindows[Entry].Y,
		  InteractMenu -> SubWindows[Entry].Str);

    InteractMenu -> SubWindows[Entry].Str = Str;       /* Update to new one. */

    GRSetColor(InteractMenu -> SubWindows[Entry].Color);/* And draw the new. */
    IntrWndwRText(InteractMenu -> SubWindows[Entry].X,
		  InteractMenu -> SubWindows[Entry].Y,
		  InteractMenu -> SubWindows[Entry].Str);

    GRPopViewPort();

    GRPopTextSetting();
}

/******************************************************************************
* A routine invoked when ever the Input window needs to be refreshed.	      *
******************************************************************************/
static void InputWndwRefreshFunction(int WindowID)
{
    IntrTextWndwRefresh(WindowID);
}

/******************************************************************************
* A function bounded to a window handling key.				      *
******************************************************************************/
static void SetMaximumBBoxSize(int WindowID)
{
   IntrBBoxStruct BBox;

   BBox.Xmin = BBox.Ymin = GlblWindowFrameWidth;
   BBox.Xmax = GRScreenMaxX - GlblWindowFrameWidth;
   BBox.Ymax = GRScreenMaxY - GlblWindowFrameWidth;

   if (WindowID == InputWindowID)
	BBox.Xmin += IntrWndwScrollBarWidth();

   IntrWndwSetResizeBBox(&BBox);
}

/******************************************************************************
* A function bounded to a window handling key.				      *
******************************************************************************/
static void PopUpMenuFunc(int KeyStroke)
{
    int WindowID;
    IntrIntFunc ViewRefreshFunc;
    IntrBBoxStruct BBox;

    if (IntrPopUpMenu(PUWndwMenu, 0)) {
	switch (PUWndwMenu -> SelectedIndex) {
	    case 0: /* Redraw all windows. */
		IntrWndwRedrawAll();
		break;
	    case 1: /* Move window. */
		if (IntrPopUpActive() == 0 &&
		    (WindowID = IntrWndwPick()) > 0)
		    IntrWndwMove(WindowID, TRUE);
		break;
	    case 2: /* Resize window. */
		if (IntrPopUpActive() == 0 &&
		    (WindowID = IntrWndwPick()) > 0) {
		    SetMaximumBBoxSize(WindowID);
		    if (WindowID == ViewWindowID) {
			/* DIsable refresh function since we change aspect. */
			ViewRefreshFunc = IntrWndwGetRefreshFunc(ViewWindowID);
			IntrWndwSetRefreshFunc(ViewWindowID, NULL);
		    }
		    IntrWndwResize(WindowID, TRUE);
		    if (WindowID == ViewWindowID) {
			SetViewWindowFBBox(WindowID);
			IntrWndwSetRefreshFunc(ViewWindowID, ViewRefreshFunc);
			IntrWndwPop(WindowID, TRUE, TRUE);
		    }
		}
		break;
	    case 3: /* Pop window. */
		if (IntrPopUpActive() == 0 &&
		    (WindowID = IntrWndwPick()) > 0)
		    IntrWndwPop(WindowID, TRUE, FALSE);
		break;
	    case 4: /* Push window. */
		if (IntrPopUpActive() == 0 &&
		    (WindowID = IntrWndwPick()) > 0)
		    IntrWndwPush(WindowID, TRUE);
		break;
	    case 5: /* Zoom window. */
		if (IntrPopUpActive() == 0 &&
		    (WindowID = IntrWndwPick()) > 0) {
    		    SetMaximumBBoxSize(WindowID);
		    if (WindowID == ViewWindowID) {
			/* DIsable refresh function since we change aspect. */
			ViewRefreshFunc = IntrWndwGetRefreshFunc(ViewWindowID);
			IntrWndwSetRefreshFunc(ViewWindowID, NULL);
		    }
		    IntrWndwFullSize(WindowID, TRUE);
		    if (WindowID == ViewWindowID) {
			SetViewWindowFBBox(WindowID);
			IntrWndwSetRefreshFunc(ViewWindowID, ViewRefreshFunc);
			IntrWndwPop(WindowID, TRUE, TRUE);
		    }
		}
		break;
	    case 6: /* Reset window sizes. */
		SetBBoxSize(&BBox, GlblViewWndwPos);
		IntrWndwSetBBox(ViewWindowID, &BBox);
		SetBBoxSize(&BBox, GlblTransWndwPos);
		IntrWndwSetBBox(TransWindowID, &BBox);
		if (HasStatusWindow) {
		    SetBBoxSize(&BBox, GlblStatusWndwPos);
		    IntrWndwSetBBox(StatusWindowID, &BBox);
		}
		if (HasInputWindow) {
		    SetBBoxSize(&BBox, GlblInputWndwPos);
    		    IntrWndwSetBBox(InputWindowID, &BBox);
		}
		IntrWndwRedrawAll();
	        break;
	    case 7: /* Headers. */
		GlblDrawHeader = !GlblDrawHeader;
		IntrWndwSetDrawHeader(ViewWindowID, GlblDrawHeader);
		IntrWndwSetDrawHeader(TransWindowID, GlblDrawHeader);
		if (HasStatusWindow)
		    IntrWndwSetDrawHeader(StatusWindowID, GlblDrawHeader);
		if (HasInputWindow)
		    IntrWndwSetDrawHeader(InputWindowID, GlblDrawHeader);
		IntrWndwRedrawAll();
		break;
	}
    }
}
[ RETURN TO DIRECTORY ]