/*****************************************************************************
*   Program to draw EE diagrams.					     *
*									     *
* Usage:								     *
*									     *
* Written by:  Gershon Elber			IBM PC Ver 2.0, Aug. 1990    *
*****************************************************************************/

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <time.h>
#include <dos.h>
#include <dir.h>
#include <alloc.h>
#include <time.h>
#include "Program.h"
#include "EELibs.h"
#include "EECreate.h"
#include "EERedraw.h"
#include "EEStatus.h"
#include "EEString.h"
#include "EEModify.h"
#include "EELoad.h"
#include "EELayer.h"
#include "Director.h"
#include "Ctrl-Brk.h"
#include "Config.h"

#define WINDOWS_FRAME_WIDTH 8
#define MAX_NUM_OF_OPEN_WINDOWS 50

#define DEFAULT_LIB_DIR "."		/* Current directory is the default. */

/* Undef DEBUG_MALLOC_TC20 iff you have TurboC 2.0. It assumes the offset    */
/* part of the pointer is always 8 which is TRUE only of TC 2.0.	     */
/* #define DEBUG_MALLOC_TC20  /* Add debugging aid for malloc/free routines. */

/* Undef DEBUG_MALLOC_TCPP iff you have TurboC++ 1.0. It uses heap testing   */
/* routines introduced in this version.					     */
/* #define DEBUG_MALLOC_TCPP  /* Add debugging aid for malloc/free routines. */

#define DIRECT_CALL_INDEX_OFFSET	100
#define MAX_KEY_BINDINGS	100

typedef struct {
    int ScanCode;	    /* Scan code to activate the following function. */
    int Menu;					    /* Pull Down Menu index. */
    int MenuEntry;			      /* Pull Down Menu entry index. */
} KeyBindingStruct;

int EESnapDistance = DEFAULT_SNAP_DISTANCE,
    EETextScale = 1,
    EEWindowsFrameWidth = 8,			   /* Width of all drawings. */
    EEListNumDisplayed = 30,
    EERootWindowID = -1,
    EERootWndwFrameColor = INTR_COLOR_MAGENTA,
    EERootWndwForeColor = INTR_COLOR_YELLOW,
    EERootWndwBackColor = INTR_COLOR_BLUE,
    EERootWndwXorColor = INTR_COLOR_CYAN,
    EEPopUpFrameColor = INTR_COLOR_RED,   /* Color for pop up menus/queries. */
    EEPopUpBackColor = INTR_COLOR_MAGENTA,
    EEPopUpForeColor = INTR_COLOR_YELLOW,
    EEPopUpXorColor = INTR_COLOR_YELLOW,
    EEActvWndwFrameColor = INTR_COLOR_RED,
    EEActvWndwForeColor = INTR_COLOR_YELLOW,
    EEActvWndwBackColor = INTR_COLOR_BLUE,
    EEPsvWndwFrameColor = INTR_COLOR_RED,
    EEPsvWndwForeColor = INTR_COLOR_YELLOW,
    EEPsvWndwBackColor = INTR_COLOR_BLUE,
    EEHighLightColor = INTR_COLOR_RED,
    EELayerWire = INTR_COLOR_WHITE,
    EELayerBus = INTR_COLOR_WHITE,
    EELayerGate = INTR_COLOR_WHITE,
    EELayerIEEE = INTR_COLOR_WHITE,
    EELayerPinFun = INTR_COLOR_WHITE,
    EELayerPinNum = INTR_COLOR_WHITE,
    EELayerPinNam = INTR_COLOR_WHITE,
    EELayerRefDes = INTR_COLOR_WHITE,
    EELayerAttr = INTR_COLOR_WHITE,
    EELayerDevice = INTR_COLOR_WHITE,
    EELayerNotes = INTR_COLOR_WHITE,
    EELayerNetNam = INTR_COLOR_WHITE,
    EELayerPin = INTR_COLOR_WHITE;
BooleanType
    EEAutoPan = FALSE,
    EEHVLineDrawing = TRUE,	    /* Draw only horizontal/ vertical lines. */
    EESubName = TRUE;
IntrBBoxStruct
    *EEActiveBBox = NULL;
EEWindowStruct
    *EEActiveWindow = NULL,	       		/* Pointer to active window. */
    *EEWindowsList = NULL;	          /* List of all open windows/files. */

static char
    *VersionStr =
	"EEDraw	IBMPC "
	EEDRAW_VERSION
	"	Gershon Elber,  "
	__DATE__ ",   " __TIME__ "\n"
	"(C) Copyright 1989-91 Gershon Elber, Non commercial use only.\n";
static char
    *UsageStr = "Usage: EEDraw [-z] *[EEDrawFile.EED]\n";
static int
    ActiveWindowID = -1,
    HelpWindowID = -1,
    LayerWindowID = -1,
    ShowWindowName = FALSE,
    Allow256Colors = FALSE,
    AllowAsyncEvents = TRUE,
    MouseExists = FALSE,
    JoyStickExists = FALSE,
    ATKeyboard = FALSE,
    MouseSensitivity = 32,
    SaveBackMethod = 0,
    GraphDriver = 0,
    KeyBindingCount = 0,
    LastKeyStroke = -1;
static char
    *LoadLibraryList = NULL,
    *SaveBackPath = NULL,
    *BGIDriverPath = NULL,
    *SVGANameMode = NULL,
    *LibrariesPathPtr = NULL,
    InitialPath[FULL_PATH_LEN],
    LibrariesPath[FULL_PATH_LEN];
static IntrCursorShapeStruct Cursor;
static IntrBBoxStruct ResizeBBox;
static KeyBindingStruct KeyBindingList[MAX_KEY_BINDINGS];

static ConfigStruct SetUp[] =
{ { "Mouse",		&MouseExists,		SU_BOOLEAN_TYPE },
  { "Joystick",		&JoyStickExists,	SU_BOOLEAN_TYPE },
  { "ATKeyboard",	&ATKeyboard,		SU_BOOLEAN_TYPE },
  { "AutoPan",		&EEAutoPan,		SU_BOOLEAN_TYPE },
  { "SubName",          &EESubName,             SU_BOOLEAN_TYPE },
  { "WindowName",	&ShowWindowName,	SU_BOOLEAN_TYPE },
  { "HVLines",		&EEHVLineDrawing,	SU_BOOLEAN_TYPE },
  { "Allow256Colors",   &Allow256Colors,	SU_BOOLEAN_TYPE },
  { "AllowAsyncEvents", &AllowAsyncEvents,	SU_BOOLEAN_TYPE },
  { "MouseSensitivity",	&MouseSensitivity,	SU_INTEGER_TYPE },
  { "SnapDistance",	&EESnapDistance,	SU_INTEGER_TYPE },
  { "SaveBackMethod",   &SaveBackMethod,	SU_INTEGER_TYPE },
  { "GraphDriver",	&GraphDriver,		SU_INTEGER_TYPE },
  { "RootFrameolor",    &EERootWndwFrameColor,  SU_INTEGER_TYPE },
  { "RootForeColor",    &EERootWndwForeColor,   SU_INTEGER_TYPE },
  { "RootBackColor",    &EERootWndwBackColor,   SU_INTEGER_TYPE },
  { "RootXorColor",     &EERootWndwXorColor,    SU_INTEGER_TYPE },
  { "ActvFrameColor",   &EEActvWndwFrameColor,  SU_INTEGER_TYPE },
  { "ActvForeColor",    &EEActvWndwForeColor,   SU_INTEGER_TYPE },
  { "ActvBackColor",    &EEActvWndwBackColor,   SU_INTEGER_TYPE },
  { "PsvFrameColor",    &EEPsvWndwFrameColor,   SU_INTEGER_TYPE },
  { "PsvForeColor",     &EEPsvWndwForeColor,    SU_INTEGER_TYPE },
  { "PsvBackColor",     &EEPsvWndwBackColor,    SU_INTEGER_TYPE },
  { "PopUpFrameColor",  &EEPopUpFrameColor,	SU_INTEGER_TYPE },
  { "PopUpBackColor",   &EEPopUpBackColor,	SU_INTEGER_TYPE },
  { "PopUpForeColor",   &EEPopUpForeColor,	SU_INTEGER_TYPE },
  { "PopUpXorColor",    &EEPopUpXorColor,	SU_INTEGER_TYPE },
  { "HighLightColor",   &EEHighLightColor,	SU_INTEGER_TYPE },
  { "LayerWire",	&EELayerWire,		SU_INTEGER_TYPE },
  { "LayerBus",		&EELayerBus,		SU_INTEGER_TYPE },
  { "LayerGate",	&EELayerGate,		SU_INTEGER_TYPE },
  { "LayerIEEE",	&EELayerIEEE,		SU_INTEGER_TYPE },
  { "LayerPinFun",	&EELayerPinFun,		SU_INTEGER_TYPE },
  { "LayerPinNum",	&EELayerPinNum,		SU_INTEGER_TYPE },
  { "LayerPinNam",	&EELayerPinNam,		SU_INTEGER_TYPE },
  { "LayerRefDes",	&EELayerRefDes,		SU_INTEGER_TYPE },
  { "LayerAttr",	&EELayerAttr,		SU_INTEGER_TYPE },
  { "LayerDevice",	&EELayerDevice,		SU_INTEGER_TYPE },
  { "LayerNotes",	&EELayerNotes,		SU_INTEGER_TYPE },
  { "LayerNetNam",	&EELayerNetNam,		SU_INTEGER_TYPE },
  { "LayerPin",		&EELayerPin,		SU_INTEGER_TYPE },
  { "FrameWidth",	&EEWindowsFrameWidth,   SU_INTEGER_TYPE },
  { "BGIDriverPath",	&BGIDriverPath,		SU_STRING_TYPE },
  { "SaveBackPath",	&SaveBackPath,		SU_STRING_TYPE },
  { "SVGANameMode",	&SVGANameMode,		SU_STRING_TYPE },
  { "Libraries",	&LoadLibraryList,	SU_STRING_TYPE },
  { "LibrariesPath",	&LibrariesPathPtr,	SU_STRING_TYPE },
};
#define NUM_SET_UP	(sizeof(SetUp) / sizeof(ConfigStruct))

extern unsigned int _stklen = 16384;	     /* Increase default stack size. */

static void MakeWindowActive(EEWindowStruct *Window, BooleanType Refresh);
static void MakeFullPathName(char *FileName);
static EEWindowStruct *LoadOneEEFile(char *FileName, BooleanType IsNew);
static void HandleFileMenu(int Index);
static void HandleWindowMenu(int Index);
static void HandleDisplayMenu(int Index);
static void HandleLibsMenu(int Index);
static void HandleDrawMenu(int Index);
static void HandleModifyMenu(int Index);
static void HandleSameAgain(int KeyStroke);
static void HandleKeyBindings(int KeyStroke);
static void HandleStatusMenu(int Index);
static int ReadKeyBindings(char *Name);
static char *GetFileName(char *FullPathName);
static void RootWndwRefreshFunc(int WindowID);
static void LayerWndwRefreshFunc(int WindowID);
static void HelpWndwRefreshFunc(int WindowID);
static void DataWndwRefreshFunc(int WindowID);

static IntrIntFunc PDActionFuncs[] = {   /* Pull Down Functions to activate. */
    HandleFileMenu,
    HandleWindowMenu,
    HandleDisplayMenu,
    HandleLibsMenu,
    HandleDrawMenu,
    HandleModifyMenu,
    HandleStatusMenu
};
static char *PDMenuStrs[] = {		      /* Pull Down Menu Entry names: */
    "File",
    "Window",
    "Display",
    "Libs",
    "Draw",
    "Modify",
    "Status"
};
#define PULL_DOWN_SIZE (sizeof(PDMenuStrs) / sizeof(char *))

static char *FilePUStrs[] = {
    "LoadEEDFile        ",
    "NewEEDFile         ",
    "SaveAllEED         ",
    "SaveEEDFile        ",
    "SaveEEDAsOld       ",
    "SaveEEDAsNew       ",
    "SaveNetList        ",
    "CloseEEDFile       ",
    "ClearAll           ",
    "Directory          ",
    "ChangeDir          ",
    "ShellToDos         ",
    "ExitEEdraw         ",
};
#define FILE_POP_UP_SIZE (sizeof(FilePUStrs) / sizeof(char *))
static IntrPopUpMenuStruct *FilePUMenu = NULL;
static char *WindowPUStrs[] = {
    "PopWindow            ",
    "PushWindow           ",
    "MoveWindow           ",
    "ResizeWindow         ",
    "FullSize             ",
    "ShowName             ",
    "MakeActive           ",
    "NameActive           ",
    "PanWindowLeft        ",
    "PanWindowRight       ",
    "PanWindowUp          ",
    "PanWindowDown        "
};
#define WINDOW_POP_UP_SIZE (sizeof(WindowPUStrs) / sizeof(char *))
static IntrPopUpMenuStruct *WindowPUMenu = NULL;
static char *DisplayPUStrs[] = {
    "ZoomOut         ",
    "ZoomIn          ",
    "ZoomReset       ",
    "RedrawAll       "
};
#define DISPLAY_POP_UP_SIZE (sizeof(DisplayPUStrs) / sizeof(char *))
static IntrPopUpMenuStruct *DisplayPUMenu = NULL;
static char *LibsPUStrs[] = {
    "LoadLibrary         ",
    "LoadLibByName       ",
    "FreeLibrary         ",
    "ViewLibrary         ",
    "DirLibrary          ",
    "ChDirLibrary        "
};
#define LIBS_POP_UP_SIZE (sizeof(LibsPUStrs) / sizeof(char *))
static IntrPopUpMenuStruct *LibsPUMenu = NULL;
static char *DrawPUStrs[] = {
    "DrawLine          ",
    "DrawWire          ",	/* Draw Conection wire, ignore Current */
				/* Layer and enable status	       */
    "DrawBus           ",
    "DrawConnect       ",
    "DrawText          ",
    "DrawLibItem       ",
    "ChangeLayer       ",
    "TglOneColor       ",
    "SetOneColor       "
};
#define DRAW_POP_UP_SIZE (sizeof(DrawPUStrs) / sizeof(char *))
static IntrPopUpMenuStruct *DrawPUMenu = NULL;
static char *ModifyPUStrs[] = {
    "ModifyMove         ",
    "ModifyCopy         ",
    "EditLibItem        ",
    "ModifyDelete       ",
    "ModifyUnDel        ",
    "ModifyCut          ",
    "ModifyPaste        ",
    "ModifyDrop         "
};
#define MODIFY_POP_UP_SIZE (sizeof(ModifyPUStrs) / sizeof(char *))
static IntrPopUpMenuStruct *ModifyPUMenu = NULL;
static char *StatusPUStrs[] = {
    "Help                ",
    "GetMemoryFree       ",
    "GetZoomFactor       ",
    "SetDrawText         ",
    "SetTextSize         ",
    "SetAutoPan          ",
    "SetHVLines          ",
    "SetSnapFactor       ",
    "SetLineWidth        "
};
#define STATUS_POP_UP_SIZE (sizeof(StatusPUStrs) / sizeof(char *))
static IntrPopUpMenuStruct *StatusPUMenu = NULL;

static char **AllPUStrs[] = {
    FilePUStrs,
    WindowPUStrs,
    DisplayPUStrs,
    LibsPUStrs,
    DrawPUStrs,
    ModifyPUStrs,
    StatusPUStrs
};
static int AllPUSizes[] = {
    FILE_POP_UP_SIZE,
    WINDOW_POP_UP_SIZE,
    DISPLAY_POP_UP_SIZE,
    LIBS_POP_UP_SIZE,
    DRAW_POP_UP_SIZE,
    MODIFY_POP_UP_SIZE,
    STATUS_POP_UP_SIZE
};
#define ALL_POP_UP_SIZE (sizeof(AllPUStrs) / sizeof(char **))

/*****************************************************************************
* Main routine - Read Parameter	line and do what you need...		     *
*****************************************************************************/
void main(int argc, char **argv)
{
    int x, y;
    IntrPullDownMenuStruct *MainPullDownMenu;

    getcwd(InitialPath, FULL_PATH_LEN);  /* Save where we were when started. */
    strcpy(LibrariesPath, DEFAULT_LIB_DIR);

    if (strcmp(argv[1], "-z") == 0) {
	fprintf(stderr, "%s%s", UsageStr, VersionStr);
	MyExit(-1);
    }

    SetUpCtrlBrk();
    SetUpHardErr();

    Config(PROGRAM_NAME, SetUp, NUM_SET_UP); /* Read config. file if exists. */
    SetColorSet();			     /* Set the baisc colour array */
    if (LibrariesPathPtr != NULL) {
	strcpy(LibrariesPath, LibrariesPathPtr);
	MyFree((VoidPtr) LibrariesPathPtr);
    };

    /* Read the key binding file and initialize the main menu accordingly: */
    if (!ReadKeyBindings(PROGRAM_NAME)) MyExit(-1);

    Cursor.CursorType = INTR_CURSOR_ARROW;
    IntrSetCursorType(&Cursor);

    if (SVGANameMode != NULL && strlen(SVGANameMode) > 0)
	GRInstallSVGA(SVGANameMode);

    if (BGIDriverPath != NULL && strlen(BGIDriverPath) > 0)
        GRSetBGIPath(BGIDriverPath);

    GRSetDefaultDriver(GraphDriver);

    IntrSetSaveBackPath(SaveBackPath);
    IntrSetSaveBackMethod(SaveBackMethod);

    IntrSetMouseSensitivity(MouseSensitivity);
    IntrSetAtKeyboard(ATKeyboard);

    IntrAllow256Colors(Allow256Colors);
    IntrSetAsyncEventMode(AllowAsyncEvents);

    /* SeedLayers();		      /* seed the layer structures */

    IntrInit();			      /* Initialize the interaction library. */

    IntrSetInputDevice(INTR_INPT_DEVICE_KEYBOARD |
    		       (MouseExists ? INTR_INPT_DEVICE_MOUSE : 0) |
                       (JoyStickExists ? INTR_INPT_DEVICE_JOYSTICK : 0));
		       
    EEListNumDisplayed = GRScreenMaxY / 20;

    MainPullDownMenu = IntrPullDownMenuCreate(PDMenuStrs, 0, PULL_DOWN_SIZE,
    					      PDActionFuncs,
                                              EERootWndwFrameColor,
                                              EERootWndwBackColor,
                                              EERootWndwForeColor,
                                              EERootWndwXorColor,
                                              EEWindowsFrameWidth);

    ResizeBBox.Xmin = EEWindowsFrameWidth;
    ResizeBBox.Xmax = GRScreenMaxX - EEWindowsFrameWidth;
    ResizeBBox.Ymin = IntrWndwGetHeaderHeight("M", EEWindowsFrameWidth) +
    						    EEWindowsFrameWidth + 2;
    ResizeBBox.Ymax = GRScreenMaxY - EEWindowsFrameWidth;

    /* Create and map to screen the root back ground window. */
    EERootWindowID = IntrWndwCreate(NULL, EEWindowsFrameWidth, &ResizeBBox,
				EERootWndwFrameColor, EERootWndwBackColor, NULL,
                                MainPullDownMenu, RootWndwRefreshFunc);
    IntrWndwSetZoom(EERootWindowID, DEFAULT_ZOOM_FACTOR);
    IntrWndwPop(EERootWindowID, TRUE, FALSE);

    ResizeBBox.Xmin += IntrWndwScrollBarWidth();
    if (ShowWindowName)
	ResizeBBox.Ymin += IntrWndwGetHeaderHeight("M", EEWindowsFrameWidth) + 2;
    ResizeBBox.Ymax -= IntrWndwScrollBarWidth();
    IntrWndwSetResizeBBox(&ResizeBBox);	   /* Set bounds to window resizing. */

    FilePUMenu = IntrPopUpMenuCreate(NULL, FilePUStrs, 0, FILE_POP_UP_SIZE,
    				     EERootWndwFrameColor, EERootWndwBackColor,
                                     EERootWndwForeColor, EERootWndwXorColor,
                                     EEWindowsFrameWidth, &Cursor);
    WindowPUMenu = IntrPopUpMenuCreate(NULL, WindowPUStrs, 0, WINDOW_POP_UP_SIZE,
    				     EERootWndwFrameColor, EERootWndwBackColor,
                                     EERootWndwForeColor, EERootWndwXorColor,
                                     EEWindowsFrameWidth, &Cursor);
    DisplayPUMenu = IntrPopUpMenuCreate(NULL, DisplayPUStrs, 0, DISPLAY_POP_UP_SIZE,
					EERootWndwFrameColor, EERootWndwBackColor,
                                        EERootWndwForeColor, EERootWndwXorColor,
                                        EEWindowsFrameWidth, &Cursor);
    LibsPUMenu = IntrPopUpMenuCreate(NULL, LibsPUStrs, 0, LIBS_POP_UP_SIZE,
    				     EERootWndwFrameColor, EERootWndwBackColor,
                                     EERootWndwForeColor, EERootWndwXorColor,
                                     EEWindowsFrameWidth, &Cursor);
    DrawPUMenu = IntrPopUpMenuCreate(NULL, DrawPUStrs, 0, DRAW_POP_UP_SIZE,
    				     EERootWndwFrameColor, EERootWndwBackColor,
                                     EERootWndwForeColor, EERootWndwXorColor,
                                     EEWindowsFrameWidth, &Cursor);
    ModifyPUMenu = IntrPopUpMenuCreate(NULL, ModifyPUStrs, 0, MODIFY_POP_UP_SIZE,
    				       EERootWndwFrameColor, EERootWndwBackColor,
                                       EERootWndwForeColor, EERootWndwXorColor,
                                       EEWindowsFrameWidth, &Cursor);
    StatusPUMenu = IntrPopUpMenuCreate(NULL, StatusPUStrs, 0, STATUS_POP_UP_SIZE,
    				       EERootWndwFrameColor, EERootWndwBackColor,
                                       EERootWndwForeColor, EERootWndwXorColor,
                                       EEWindowsFrameWidth, &Cursor);

    if (LoadLibraryList != NULL) {
	LoadLibraries(LoadLibraryList);
	MyFree((VoidPtr) LoadLibraryList);
	LoadLibraryList = NULL;
    }

    /* Load All files specified in the command line. */
    while (argc-- > 1)
        LoadOneEEFile(*++argv, FALSE);

    /* Query events forever. From this point everything is events driven     */
    /* and we need do nothing beyond this infinite event query.		     */
    while (TRUE) {
	GRSetViewPort(0, 0, GRScreenMaxX, GRScreenMaxY);
        if (IntrGetEventWait(&x, &y) == INTR_EVNT_MIDDLE_BUTTON)
	    HandleSameAgain(0);
    }
}

/*****************************************************************************
* Routine to handle the FILE pull down sub menu.			     *
*****************************************************************************/
static void MakeWindowActive(EEWindowStruct *Window, BooleanType Refresh)
{
    if (EEActiveWindow == Window) return;

    /* If there is current active window - inactivate it. */
    if (ActiveWindowID >= 0) {
	IntrWndwSetFrameColor(EEActiveWindow -> IntrLibWindowID,
			      EEPsvWndwFrameColor);
	IntrWndwSetBackGroundColor(EEActiveWindow -> IntrLibWindowID,
			           EEPsvWndwBackColor);
        IntrWndwSetScrlBar(EEActiveWindow -> IntrLibWindowID, TRUE,
			   INTR_SCRLBAR_LEFT, EEPsvWndwForeColor);
        IntrWndwSetScrlBar(EEActiveWindow -> IntrLibWindowID, FALSE,
			   INTR_SCRLBAR_BOTTOM, EEPsvWndwForeColor);
	if (Refresh)
            IntrWndwPop(EEActiveWindow -> IntrLibWindowID, TRUE, FALSE);
    }

    EEActiveWindow = Window;
    ActiveWindowID = EEActiveWindow -> IntrLibWindowID;
    EEActiveBBox = IntrWndwGetBBox(ActiveWindowID);
    IntrWndwSetFrameColor(EEActiveWindow -> IntrLibWindowID,
			  EEActvWndwFrameColor);
    IntrWndwSetBackGroundColor(EEActiveWindow -> IntrLibWindowID,
			       EEActvWndwBackColor);
    IntrWndwSetScrlBar(EEActiveWindow -> IntrLibWindowID, TRUE,
		       INTR_SCRLBAR_LEFT, EEActvWndwForeColor);
    IntrWndwSetScrlBar(EEActiveWindow -> IntrLibWindowID, FALSE,
		       INTR_SCRLBAR_BOTTOM, EEActvWndwForeColor);
    if (Refresh)
        IntrWndwPop(EEActiveWindow -> IntrLibWindowID, TRUE, FALSE);
}

/*****************************************************************************
* Routine to make sure the cursor is positioned in the active window.        *
*****************************************************************************/
void PutCursorInActiveWindow(void)
{
    if (EEActiveBBox -> Xmin > GRCurrentCursorX ||
	EEActiveBBox -> Xmax < GRCurrentCursorX ||
	EEActiveBBox -> Ymin > GRCurrentCursorY ||
	EEActiveBBox -> Ymax < GRCurrentCursorY) {
	GRCurrentCursorX = (EEActiveBBox -> Xmin + EEActiveBBox -> Xmax) / 2;
	GRCurrentCursorY = (EEActiveBBox -> Ymin + EEActiveBBox -> Ymax) / 2;
    }
}

/*****************************************************************************
* Routine to expand a file name to be a full path if necessary.		     *
*****************************************************************************/
static void MakeFullPathName(char *FileName)
{
    int Mask;
    char Drive[3], Dir[66], Name[9], Ext[5];

    Mask = fnsplit(FileName, Drive, Dir, Name, Ext);

    if (!(Mask & DRIVE)) {
	Drive[0] = getdisk() + 'A';
	Drive[1] = ':';
	Drive[2] = 0;
    }
    if (!(Mask & DIRECTORY)) {
    	strcpy(Dir, "\\");
    	getcurdir(Drive[0] - 'A' + 1, &Dir[1]);
    }

    fnmerge(FileName, Drive, Dir, Name, Ext);
    strlwr(FileName);
}

/*****************************************************************************
* Routine to handle file loading. If given file name is NULL the name is     *
* queried (within LoadEEFile).						     *
* However if IsNew then no file is loaded.				     *
*****************************************************************************/
static EEWindowStruct *LoadOneEEFile(char *FileName, BooleanType IsNew)
{
    EEWindowStruct
        *Window = (EEWindowStruct *) MyMalloc(sizeof(EEWindowStruct));

    if (FileName != NULL)
	strcpy(Window -> FileName, FileName);
    else
	Window -> FileName[0] = 0;

	SeedLayers(Window);
    Window -> EEDrawList = NULL;
    Window -> IntrLibWindowID = -1;
    Window -> Modified = FALSE;
    if (IsNew || LoadEEFile(Window)) {
	if (strlen(Window -> FileName) == 0)
	    strcpy(Window -> FileName, "noname.eed");
        /* Expand the file name to full path if necessary: */
	MakeFullPathName(Window ->FileName);

        Window -> PageXSize = PAGE_A4_XSIZE;
        Window -> PageYSize = PAGE_A4_YSIZE;
	Window -> IsFullSize = FALSE;
	Window -> IntrLibWindowID =
            IntrWndwCreate(ShowWindowName ? Window -> FileName : NULL,
            		   EEWindowsFrameWidth, &ResizeBBox,
			   EEActvWndwFrameColor, EEActvWndwBackColor,
                           NULL, NULL, DataWndwRefreshFunc);
        /* ShowStatus(Window); */
        IntrWndwSetScrlBar(Window -> IntrLibWindowID, TRUE,
			   INTR_SCRLBAR_LEFT, EEActvWndwForeColor);
        IntrWndwSetScrlBar(Window -> IntrLibWindowID, FALSE,
			   INTR_SCRLBAR_BOTTOM, EEActvWndwForeColor);
	IntrWndwSetZoom(Window -> IntrLibWindowID, DEFAULT_ZOOM_FACTOR);
	IntrWndwSetPanning(Window -> IntrLibWindowID,
        		   DEFAULT_INV_ZOOM(Window -> PageXSize) / 2,
                           DEFAULT_INV_ZOOM(Window -> PageYSize) / 2);
        Window -> Pnext = EEWindowsList;
        EEWindowsList = Window;
        IntrWndwResize(Window -> IntrLibWindowID, FALSE);
        MakeWindowActive(Window, FALSE);
        ShowStatus(Window,0);
        return Window;
    }
    else {
	MyFree((VoidPtr) Window);
	return NULL;
    }
}

/*****************************************************************************
* Routine to handle the FILE pull down sub menu.			     *
*****************************************************************************/
static void HandleFileMenu(int Index)
{
    int NumOfFiles, WindowID;
    char Line[LINE_LEN], Buffer[LINE_LEN];
    FileNameType *FileNames;
    EEWindowStruct *TWindow, *Window;

    if (Index >= 0) {
	if (IntrPopUpMenu(FilePUMenu, INTR_WNDW_PULL_DOWN))
	    Index = FilePUMenu -> SelectedIndex;
        else
            Index = -1;
    }
    else
	Index += DIRECT_CALL_INDEX_OFFSET;

    GRSetViewPort(0, 0, GRScreenMaxX, GRScreenMaxY);

    switch(Index) {
    	case 0: /* Load EED File */
	    LoadOneEEFile(NULL, FALSE);
            break;
    	case 1: /* New EED File */
	    LoadOneEEFile(NULL, TRUE);
            break;
	case 2: /* Save All EED */
            for (Window = EEWindowsList;
                 Window != NULL;
                 Window = Window -> Pnext)
                if (Window -> Modified) {
                    IntrDrawMessage(Window -> FileName, EEPopUpForeColor,
                				        EEPopUpBackColor);
                    if (SaveEEFile(FILE_SAVE_AS, Window)) {
                    	Window -> Modified = FALSE;
                    
                    }
		    IntrEraseMessage();
                }
            if (ShowWindowName){
		ShowStatus(Window,0);
		IntrWndwRedrawAll();
	    }
	    break;
	case 3: /* Save EED As */
	    if (ActiveWindowID < 0) {
		IntrQueryContinue("No active window to save.",
			  EEPopUpFrameColor, EEPopUpBackColor, EEPopUpForeColor,
			  EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
			  INTR_WNDW_PLACE_CENTER);
		break;
	    }
	    if (!EEActiveWindow -> Modified) {
		IntrQueryContinue("Active file has not been modified",
				  EEPopUpFrameColor, EEPopUpBackColor,
				  EEPopUpForeColor, EEPopUpXorColor,
				  EEWindowsFrameWidth, &Cursor,
				  INTR_WNDW_PLACE_CENTER);
		break;
	    }
	    if (SaveEEFile(FILE_SAVE_AS, EEActiveWindow)) {
		EEActiveWindow -> Modified = FALSE;
	 
	    }
	    break;
	case 4: /* Save EED Old */
	    if (ActiveWindowID < 0) {
		IntrQueryContinue("No active window to save.",
			  EEPopUpFrameColor, EEPopUpBackColor, EEPopUpForeColor,
			  EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
			  INTR_WNDW_PLACE_CENTER);
		break;
	    }
	    if (SaveEEFile(FILE_SAVE_OLD, EEActiveWindow)) {
		EEActiveWindow -> Modified = FALSE;
		 

		/* Expand the file name to full path: */
		MakeFullPathName(EEActiveWindow -> FileName);

		if (ShowWindowName) {
		    IntrWndwSetName(EEActiveWindow -> IntrLibWindowID,
				    EEActiveWindow -> FileName);
		    IntrWndwPop(EEActiveWindow -> IntrLibWindowID, TRUE, FALSE);
		}
	    }
	    break;
	case 5: /* Save EED New */
	    if (ActiveWindowID < 0) {
		IntrQueryContinue("No active window to save.",
			  EEPopUpFrameColor, EEPopUpBackColor, EEPopUpForeColor,
			  EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
			  INTR_WNDW_PLACE_CENTER);
		break;
	    }
	    if (SaveEEFile(FILE_SAVE_NEW, EEActiveWindow)) {
		EEActiveWindow -> Modified = FALSE;
		 

		/* Expand the file name to full path: */
		MakeFullPathName(EEActiveWindow -> FileName);

		if (ShowWindowName) {
		    IntrWndwSetName(EEActiveWindow -> IntrLibWindowID,
				    EEActiveWindow -> FileName);
		    IntrWndwPop(EEActiveWindow -> IntrLibWindowID, TRUE, FALSE);
		}
	    }
	    break;
	case 6: /* Save Net List */
	    if (ActiveWindowID < 0) {
		IntrQueryContinue("No active window to save.",
			  EEPopUpFrameColor, EEPopUpBackColor, EEPopUpForeColor,
			  EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
			  INTR_WNDW_PLACE_CENTER);
		break;
	    }
	    SaveNetList(EEActiveWindow);
	    break;
	case 7: /* Close EED File */
	    if ((WindowID = IntrWndwPick()) > 0 && WindowID != EERootWindowID) {
		for (Window = EEWindowsList;
		     Window != NULL;
		     Window = Window -> Pnext)
		    if (Window -> IntrLibWindowID == WindowID) break;
		if (Window == NULL) break;

		if (Window -> Modified &&
		    !IntrQueryYesNo("Window modified - delete?",
			EEPopUpFrameColor, EEPopUpBackColor, EEPopUpForeColor,
			EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
			INTR_WNDW_PLACE_CENTER))
		    break;

		/* Delete the window from window list */
		if (EEWindowsList != Window) {
		    for (TWindow = EEWindowsList;
			 TWindow -> Pnext != Window;
			 TWindow = TWindow -> Pnext);
		    TWindow -> Pnext = TWindow -> Pnext -> Pnext;
		}
		else
		    EEWindowsList = EEWindowsList -> Pnext;

		CloseEEDFile(Window);

		if (Window == EEActiveWindow) {
		    ActiveWindowID = -1;
		    EEActiveWindow = NULL;
		    if (EEWindowsList != NULL)
			MakeWindowActive(EEWindowsList, FALSE);
		}
		IntrWndwRedrawAll();
	    }
	    break;
	case 8: /* Clear All */
	    if ((WindowID = IntrWndwPick()) > 0 && WindowID != EERootWindowID) {
		for (Window = EEWindowsList;
		     Window != NULL;
		     Window = Window -> Pnext)
		    if (Window -> IntrLibWindowID == WindowID) break;
		if (Window == NULL) break;

		if (ClearDrawList(Window)) {
		    Window -> Modified = TRUE;
		    ShowStatus(Window,0);
		}
	    }
	    break;
	case 9: /* Directory */
	    if ((FileNames = GetFileNamesDir("*.*", ".", &NumOfFiles))
								!= NULL) {
		qsort(FileNames, NumOfFiles, sizeof(FileNameType),
		      (int (*)(const void *, const void *)) strcmp);
		IntrQueryList("Directory", (char **) FileNames,
			 sizeof(FileNameType), NumOfFiles, EEListNumDisplayed,
			 EEPopUpFrameColor, EEPopUpBackColor, EEPopUpForeColor,
			 EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
			 INTR_WNDW_PLACE_CENTER);
		MyFree((VoidPtr) FileNames);
	    }
	    break;
	case 10: /* New Dir */
	    getcwd(Line, LINE_LEN - 1);
	    sprintf(Buffer, "New dir (%s):", Line);
	    IntrQueryLine(Buffer, Line, LINE_LEN - 1, EEPopUpFrameColor,
			  EEPopUpBackColor, EEPopUpForeColor,
			  EEWindowsFrameWidth, INTR_WNDW_PLACE_CENTER);
	    if (ChangeDir(Line) != CD_OK) {
		GRTone(1400, 100);			 /* Do some noise... */
		GRTone( 400, 100);
	    }
	    break;
	case 11: /* Push to DOS */
	    /* Look for unsaved file and if found one - issue a warning. */
	    for (Window = EEWindowsList;
		 Window != NULL;
		 Window = Window -> Pnext)
		if (Window -> Modified) {
		    if (IntrQueryYesNo("Not all files are saved, save first?",
				       EEPopUpFrameColor, EEPopUpBackColor,
				       EEPopUpForeColor, EEPopUpXorColor,
				       EEWindowsFrameWidth, &Cursor,
				       INTR_WNDW_PLACE_CENTER)) {
			HandleFileMenu(2 - DIRECT_CALL_INDEX_OFFSET);
		    }
		    break;
		}

	    DosSystem();
	    break;
	case 12: /* Exit */
	    /* Look for unsaved file and if found one - issue a warning. */
	    for (Window = EEWindowsList;
		 Window != NULL;
		 Window = Window -> Pnext)
		if (Window -> Modified) {
		    if (IntrQueryYesNo("Not all files are saved, save first?",
				       EEPopUpFrameColor, EEPopUpBackColor,
				       EEPopUpForeColor, EEPopUpXorColor,
				       EEWindowsFrameWidth, &Cursor,
				       INTR_WNDW_PLACE_CENTER)) {
			HandleFileMenu(2 - DIRECT_CALL_INDEX_OFFSET);
		    }
		    break;
		}

	    IntrInputFlush();      /* Make sure we do not exit accidentally. */
	    if (IntrQueryYesNo("Exit EEDRAW", EEPopUpFrameColor,
			       EEPopUpBackColor, EEPopUpForeColor,
			       EEPopUpXorColor, EEWindowsFrameWidth,
			       &Cursor, INTR_WNDW_PLACE_CENTER))
		MyExit(0);
    }
}

/*****************************************************************************
* Routine to handle the WINDOW pull down sub menu.			     *
*****************************************************************************/
static void HandleWindowMenu(int Index)
{
    int i, WindowID;
    char **Names;
    EEWindowStruct *Window;
    IntrBBoxStruct *BBox;

    if (ActiveWindowID < 0 && HelpWindowID < 0) {
	IntrQueryContinue("No windows to work on.",
        		  EEPopUpFrameColor, EEPopUpBackColor, EEPopUpForeColor,
                          EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
                          INTR_WNDW_PLACE_CENTER);
        return;
    }

    if (Index >= 0) {
	if (IntrPopUpMenu(WindowPUMenu, INTR_WNDW_PULL_DOWN))
	    Index = WindowPUMenu -> SelectedIndex;
        else
            Index = -1;
    }
    else
	Index += DIRECT_CALL_INDEX_OFFSET;

    GRSetViewPort(0, 0, GRScreenMaxX, GRScreenMaxY);

    switch(Index) {
	case 0: /* Pop */
            if ((WindowID = IntrWndwPick()) > 0 && WindowID != EERootWindowID)
                IntrWndwPop(WindowID, TRUE, FALSE);
            break;
	case 1: /* Push */
            if ((WindowID = IntrWndwPick()) > 0 && WindowID != EERootWindowID) {
                IntrWndwPush(WindowID, FALSE);
                IntrWndwPush(EERootWindowID, TRUE);
            }
            break;
        case 2: /* Move. */
	    if ((WindowID = IntrWndwPick()) > 0 && WindowID != EERootWindowID)
 		IntrWndwMove(WindowID, TRUE);
            break;
        case 3: /* Resize. */
            if ((WindowID = IntrWndwPick()) > 0 && WindowID != EERootWindowID) {
		if (WindowID == HelpWindowID) {
		    /* Set bounds to help window resizing (no bottom scrlbar). */
                    ResizeBBox.Ymax += IntrWndwScrollBarWidth();
		    IntrWndwSetResizeBBox(&ResizeBBox);
		}

                IntrWndwResize(WindowID, TRUE);

		if (WindowID == HelpWindowID) {
		    /* Set bounds back to default window resizing. */
                    ResizeBBox.Ymax -= IntrWndwScrollBarWidth();
		    IntrWndwSetResizeBBox(&ResizeBBox);
                }
            }
	    break;
        case 4: /* Full Size. */
            if ((WindowID = IntrWndwPick()) > 0 && WindowID != EERootWindowID)
	        for (Window = EEWindowsList;
		     Window != NULL;
	             Window = Window -> Pnext)
                    if (WindowID == Window -> IntrLibWindowID) {
                        if (Window -> IsFullSize) {
			    IntrWndwSetBBox(WindowID, &Window -> BBox);
			    IntrWndwRedrawAll();
                        }
                        else {
			    BBox = IntrWndwGetBBox(WindowID);
                            Window -> BBox = *BBox;
			    IntrWndwSetBBox(WindowID, &ResizeBBox);
			    IntrWndwPop(WindowID, TRUE, FALSE);
                        }
                        Window -> IsFullSize = !Window -> IsFullSize;
                        break;
                    }
            break;
        case 5: /* Show Window Name. */
            /* The ! below on both sides guarantee boolean values only... */
	    if (!ShowWindowName !=
                !IntrQueryYesNo("Show Window Names", EEPopUpFrameColor,
                	       EEPopUpBackColor, EEPopUpForeColor,
                               EEPopUpXorColor, EEWindowsFrameWidth,
                               &Cursor, INTR_WNDW_PLACE_CENTER)) {
		ShowWindowName = !ShowWindowName;

		if (ShowWindowName)
		    ResizeBBox.Ymin += IntrWndwGetHeaderHeight("M",
			                              EEWindowsFrameWidth) + 2;
		else
		    ResizeBBox.Ymin -= IntrWndwGetHeaderHeight("M",
						      EEWindowsFrameWidth) + 2;
		IntrWndwSetResizeBBox(&ResizeBBox);

	        for (Window = EEWindowsList;
        	     Window != NULL;
	             Window = Window -> Pnext) {
                    /* Make sure min. Y does not cover the Pull Down Menu. */
		    BBox = IntrWndwGetBBox(Window -> IntrLibWindowID);
                    if (BBox -> Ymin < ResizeBBox.Ymin)
			BBox -> Ymin = ResizeBBox.Ymin;

		    IntrWndwSetName(Window -> IntrLibWindowID,
				    ShowWindowName ? Window -> FileName : NULL);
		}
                if (HelpWindowID >= 0) {
		    BBox = IntrWndwGetBBox(HelpWindowID);
                    if (BBox -> Ymin < ResizeBBox.Ymin)
		        BBox -> Ymin = ResizeBBox.Ymin;

		    IntrWndwSetName(HelpWindowID,
				    ShowWindowName ? "Help" : NULL);
                }

                IntrWndwRedrawAll();
            }
            break;
        case 6: /* Make Window Active. */
            if ((WindowID = IntrWndwPick()) > 0 && WindowID != EERootWindowID) {
	        for (Window = EEWindowsList;
        	     Window != NULL;
	             Window = Window -> Pnext)
                    if (WindowID == Window -> IntrLibWindowID) {
                        MakeWindowActive(Window, TRUE);
                        break;
                    }
	    }
            break;
        case 7: /* Make Window Active by Name. */
	    for (Window = EEWindowsList, i = 0;    /* Find how many windows. */
                 Window != NULL;
	         Window = Window -> Pnext, i++);
	    Names = (char **) MyMalloc(sizeof(char *) * i);
	    for (Window = EEWindowsList, i = 0;   /* Prepare array of names. */
		 Window != NULL;
	         Window = Window -> Pnext)
                Names[i++] = GetFileName(Window -> FileName);
	    i = IntrQueryList("File Names", Names, 0, i, EEListNumDisplayed,
                         EEPopUpFrameColor, EEPopUpBackColor, EEPopUpForeColor,
                         EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
                         INTR_WNDW_PLACE_CENTER);
            MyFree((VoidPtr) Names);
            if (i >= 0) {      /* If was selection - find window and select. */
		for (Window = EEWindowsList;
                     i-- > 0;
	             Window = Window -> Pnext);
                MakeWindowActive(Window, TRUE);
            }
	    break;
	case 8: /* Pan left */
    	    IntrWndwUpdatePanning(EEActiveWindow -> IntrLibWindowID,
				  (GRInvMapX(EEActiveBBox -> Xmin) -
		                       GRInvMapX(EEActiveBBox -> Xmax)) / 2, 0);
	    IntrWndwPop(EEActiveWindow -> IntrLibWindowID, TRUE, FALSE);
	    break;
	case 9: /* Pan right */
    	    IntrWndwUpdatePanning(EEActiveWindow -> IntrLibWindowID,
				  (GRInvMapX(EEActiveBBox -> Xmax) -
		                       GRInvMapX(EEActiveBBox -> Xmin)) / 2, 0);
	    IntrWndwPop(EEActiveWindow -> IntrLibWindowID, TRUE, FALSE);
	    break;
	case 10: /* Pan up */
    	    IntrWndwUpdatePanning(EEActiveWindow -> IntrLibWindowID, 0,
				  (GRInvMapX(EEActiveBBox -> Ymin) -
		                       GRInvMapX(EEActiveBBox -> Ymax)) / 2);

	    IntrWndwPop(EEActiveWindow -> IntrLibWindowID, TRUE, FALSE);
	    break;
	case 11: /* Pan down */
    	    IntrWndwUpdatePanning(EEActiveWindow -> IntrLibWindowID, 0,
				  (GRInvMapX(EEActiveBBox -> Ymax) -
		                       GRInvMapX(EEActiveBBox -> Ymin)) / 2);
	    IntrWndwPop(EEActiveWindow -> IntrLibWindowID, TRUE, FALSE);
	    break;

    }
}

/*****************************************************************************
* Routine to handle the DISPLAY pull down sub menu.			     *
*****************************************************************************/
static void HandleDisplayMenu(int Index)
{
    if (ActiveWindowID < 0) {
	IntrQueryContinue("No active window to work on.",
        		  EEPopUpFrameColor, EEPopUpBackColor, EEPopUpForeColor,
                          EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
                          INTR_WNDW_PLACE_CENTER);
        return;
    }

    if (Index >= 0) {
	if (IntrPopUpMenu(DisplayPUMenu, INTR_WNDW_PULL_DOWN))
	    Index = DisplayPUMenu -> SelectedIndex;
        else
            Index = -1;
    }
    else
	Index += DIRECT_CALL_INDEX_OFFSET;

    GRSetViewPort(0, 0, GRScreenMaxX, GRScreenMaxY);

    switch(Index) {
	case 0:
	    if (IntrWndwGetZoomFactor(ActiveWindowID) -
            	DEFAULT_ZOOM_FACTOR >= 4)
    		IntrQueryContinue("Zoom value is out of range",
    				  EEPopUpFrameColor, EEPopUpBackColor,
                                  EEPopUpForeColor, EEPopUpXorColor,
                                  EEWindowsFrameWidth, &Cursor,
                                  INTR_WNDW_PLACE_CENTER);
            else {
		IntrWndwUpdateZoom(ActiveWindowID, 1);
		IntrWndwPop(ActiveWindowID, TRUE, FALSE);
            }
	    break;
        case 1:
	    if (IntrWndwGetZoomFactor(ActiveWindowID) -
            	DEFAULT_ZOOM_FACTOR <= -4)
    		IntrQueryContinue("Zoom value is out of range",
    				  EEPopUpFrameColor, EEPopUpBackColor,
                                  EEPopUpForeColor, EEPopUpXorColor,
				  EEWindowsFrameWidth, &Cursor,
                                  INTR_WNDW_PLACE_CENTER);
            else {
		IntrWndwUpdateZoom(ActiveWindowID, -1);
		IntrWndwPop(ActiveWindowID, TRUE, FALSE);
            }
	    break;
	case 2:
	    IntrWndwSetZoom(ActiveWindowID, DEFAULT_ZOOM_FACTOR);
	    IntrWndwPop(ActiveWindowID, TRUE, FALSE);
	    break;
	case 3:
	    IntrWndwRedrawAll();
	    break;
    }
}

/*****************************************************************************
* Routine to handle the LIBS pull down sub menu.			     *
*****************************************************************************/
static void HandleLibsMenu(int Index)
{
    int NumOfFiles;
    char Line[LINE_LEN], Buffer[LINE_LEN], CrntPath[FULL_PATH_LEN];
    FileNameType *FileNames;

    if (Index >= 0) {
	if (IntrPopUpMenu(LibsPUMenu, INTR_WNDW_PULL_DOWN))
	    Index = LibsPUMenu -> SelectedIndex;
	else
	    Index = -1;
    }
    else
	Index += DIRECT_CALL_INDEX_OFFSET;

    GRSetViewPort(0, 0, GRScreenMaxX, GRScreenMaxY);

    getcwd(CrntPath, FULL_PATH_LEN - 1);
    ChangeDir(LibrariesPath);

    switch(Index) {
	case 0:
	    LoadLibrary();
	    break;
	case 1:
	    Line[0] = 0;
	    IntrQueryLine("New library(ies) to load:", Line, LINE_LEN - 1,
			  EEPopUpFrameColor,
			  EEPopUpBackColor, EEPopUpForeColor,
			  EEWindowsFrameWidth, INTR_WNDW_PLACE_CENTER);
	    LoadLibraries(Line);
	    break;
	case 2:
	    FreeLibrary(NULL);
	    break;
	case 3:
	    ViewLibrary();
	    break;
	case 4:
	    if ((FileNames = GetFileNamesDir("*.lib", ".", &NumOfFiles))
								!= NULL) {
		qsort(FileNames, NumOfFiles, sizeof(FileNameType),
		      (int (*)(const void *, const void *)) strcmp);
		IntrQueryList("Directory", (char **) FileNames,
			 sizeof(FileNameType), NumOfFiles, EEListNumDisplayed,
			 EEPopUpFrameColor, EEPopUpBackColor, EEPopUpForeColor,
			 EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
			 INTR_WNDW_PLACE_CENTER);
		MyFree((VoidPtr) FileNames);
	    }
	    break;
	case 5:
	    strcpy(Line, LibrariesPath);
	    sprintf(Buffer, "New lib dir (%s):", LibrariesPath);
	    IntrQueryLine(Buffer, Line, LINE_LEN - 1, EEPopUpFrameColor,
			  EEPopUpBackColor, EEPopUpForeColor,
			  EEWindowsFrameWidth, INTR_WNDW_PLACE_CENTER);
	    if (ChangeDir(Line) != CD_OK) {
		GRTone(1400, 100);			 /* Do some noise... */
		GRTone( 400, 100);
	    }
	    else
		strcpy(LibrariesPath, Line);
	    break;
    }

    ChangeDir(CrntPath);
}

/*****************************************************************************
* Routine to handle the DRAW pull down sub menu.			     *
*****************************************************************************/
static void HandleDrawMenu(int Index)
{
    DrawGenericStruct
        *NewDrawStruct = NULL;
    int i;
   
    if (ActiveWindowID < 0) {
	IntrQueryContinue("No active window to work on.",
        		  EEPopUpFrameColor, EEPopUpBackColor, EEPopUpForeColor,
                          EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
                          INTR_WNDW_PLACE_CENTER);
        return;
    }

    if (Index >= 0) {
	if (IntrPopUpMenu(DrawPUMenu, INTR_WNDW_PULL_DOWN))
	    Index = DrawPUMenu -> SelectedIndex;
	else
            Index = -1;
    }
    else
	Index += DIRECT_CALL_INDEX_OFFSET;

    GRSetViewPort(EEActiveBBox -> Xmin, EEActiveBBox -> Ymin,
    		  EEActiveBBox -> Xmax, EEActiveBBox -> Ymax);
    IntrPushCursorType();           /* Make sure cursor is IN active window. */
    PutCursorInActiveWindow();

    switch(Index) {
    	case 0:		/* Draw Polly Line */
	    NewDrawStruct = CreateNewPolylineStruct(ReturnCurrentWidth(),
			FALSE);
	    break;
    	case 1:		/* Draw Wire Connection */
	    NewDrawStruct = CreateNewPolylineStruct(ReturnCurrentWidth(),
			TRUE);
	    break;
	case 2:		/* Draw Bus Width Line Current Layer */
	    NewDrawStruct = CreateNewPolylineStruct(GR_THICK_WIDTH,FALSE);
	    break;
	case 3:
	    NewDrawStruct = CreateNewConnectionStruct();
	    break;
	case 4:
	    NewDrawStruct = CreateNewTextStruct();
	    break;
    	case 5:
	    NewDrawStruct = LibCreateNewPart();
	    break;
	case 6:		/* Change Drawing Layer */
            SetLayer(); 
	    /* IntrWndwPop(EEActiveWindow->IntrLibWindowID ,TRUE,FALSE); */
	    ShowStatus(EEActiveWindow,0);
	    break;
	case 7 :
	    SetCommonColor();
	    /* IntrWndwPop(EEActiveWindow->IntrLibWindowID ,TRUE,FALSE); */
	    ShowStatus(EEActiveWindow,0);
	    break;
	case 8 :
	    i=SetColor();
	    if(i!=-1){
		LayerPointer->CommonColor=i;
	        ShowStatus(EEActiveWindow,0);
	    }
	    break;
    }

    if (NewDrawStruct != NULL) {
    	NewDrawStruct -> Pnext = EEActiveWindow -> EEDrawList;
    	EEActiveWindow -> EEDrawList = NewDrawStruct;
        if (!EEActiveWindow -> Modified) {
	    EEActiveWindow -> Modified = TRUE;
	    
        } 
    }
    
    IntrPopCursorType();
}

/*****************************************************************************
* Routine to handle the MODIFY pull down sub menu.			     *
*****************************************************************************/
static void HandleModifyMenu(int Index)
{
    BooleanType
	Modified = FALSE;
    DrawGenericStruct *DrawStruct;

    if (ActiveWindowID < 0) {
	IntrQueryContinue("No active window to work on.",
        		  EEPopUpFrameColor, EEPopUpBackColor, EEPopUpForeColor,
                          EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
                          INTR_WNDW_PLACE_CENTER);
        return;
    }

    if (Index >= 0) {
	if (IntrPopUpMenu(ModifyPUMenu, INTR_WNDW_PULL_DOWN))
	    Index = ModifyPUMenu -> SelectedIndex;
        else
            Index = -1;
    }
    else
	Index += DIRECT_CALL_INDEX_OFFSET;

    GRSetViewPort(EEActiveBBox -> Xmin, EEActiveBBox -> Ymin,
    		  EEActiveBBox -> Xmax, EEActiveBBox -> Ymax);
    IntrPushCursorType();           /* Make sure cursor is IN active window. */
    PutCursorInActiveWindow();

    switch(Index) {
    	case 0: /* Move */
    	    Modified = (DrawStruct = PickStruct("Pick struct to move:", FALSE))
							    	    != NULL &&
		        MoveStruct(DrawStruct);
    	    break;
    	case 1: /* Copy */
	    Modified = (DrawStruct = PickStruct("Pick struct to copy", FALSE))
							    	    != NULL &&
			CopyStruct(DrawStruct);
    	    break;
    	case 2: /* EditLibItem */
	    Modified = EditLibraryItem();
	    break;
	case 3: /* Delete */
	    if ((DrawStruct = PickStruct("Pick struct to delete", FALSE))
							    	    != NULL) {
		DeleteStruct(DrawStruct);
                Modified = TRUE;
            }
    	    break;
    	case 4: /* Undelete */
	    Modified = UnDeleteStruct();
	    break;
	case 5: /* Cut */
	    if ((DrawStruct = PickStruct("Pick struct to cut", FALSE))
							    	    != NULL) {
		CutStruct(DrawStruct);
            }
    	    break;
        case 6: /* Paste */
	    Modified = PasteStruct();
    	    break;
        case 7: /* Drop */
	    DropStruct();
    	    break;
    }

    if (Modified && !EEActiveWindow -> Modified) {
	EEActiveWindow -> Modified = TRUE;
	 
    }
    IntrPopCursorType();
}

/*****************************************************************************
* Routine to handle the STATUS pull down sub menu.			     *
*****************************************************************************/
static void HandleStatusMenu(int Index)
{
    int i, NumLines;
    char *FullFileName, Line[LINE_LEN];
    FILE *f;

    if (Index >= 0) {
	if (IntrPopUpMenu(StatusPUMenu, INTR_WNDW_PULL_DOWN))
	    Index = StatusPUMenu -> SelectedIndex;
        else
            Index = -1;
    }
    else
	Index += DIRECT_CALL_INDEX_OFFSET;

    switch(Index) {
        case 0: /* Help */
	    if (HelpWindowID >= 0) {
		IntrWndwDelete(HelpWindowID, TRUE);
		HelpWindowID = -1;
            }
            else {
		if (coreleft() < 30000L) {
    		    IntrQueryContinue("Not enough memory to pop help",
    				  EEPopUpFrameColor, EEPopUpBackColor,
                                  EEPopUpForeColor, EEPopUpXorColor,
                                  EEWindowsFrameWidth, &Cursor,
                                  INTR_WNDW_PLACE_CENTER);
                    break;
                }

                sprintf(Line, "%s.hlp", PROGRAM_NAME);
                if ((FullFileName = searchpath(Line)) != NULL &&
		    (f = fopen(FullFileName, "rt")) != NULL &&
                    fgets(Line, LINE_LEN - 2, f) != NULL &&
                    sscanf(Line, "%d", &NumLines) == 1) {
		    IntrDrawMessage("Loading Help...", EEPopUpForeColor,
                				       EEPopUpBackColor);

                    /* Unlike drawing window no horizontal scroll bar. */
                    ResizeBBox.Ymax += IntrWndwScrollBarWidth();
	            HelpWindowID = IntrWndwCreate(
                    	ShowWindowName ? "Help" : NULL, EEWindowsFrameWidth,
                        &ResizeBBox, EERootWndwFrameColor, EERootWndwBackColor,
                        NULL, NULL, HelpWndwRefreshFunc);
		    ResizeBBox.Ymax -= IntrWndwScrollBarWidth();

		    IntrTextInitWindow(HelpWindowID, FALSE, EERootWndwForeColor,
				   EERootWndwForeColor,
			 	   INTR_SCRLBAR_NONE, INTR_SCRLBAR_LEFT,
                                   NumLines, 80);

        	    for (i = 0; i < NumLines; i++) {
		        fgets(Line, LINE_LEN - 2, f);
		        IntrPrintf(HelpWindowID, FALSE, Line);
                    }

                    fclose(f);

                    IntrEraseMessage();

		    IntrWndwResize(HelpWindowID, FALSE);
                    IntrWndwPop(HelpWindowID, TRUE, FALSE);
                }
                else {
    		    IntrQueryContinue("Can not open help file",
    				  EEPopUpFrameColor, EEPopUpBackColor,
                                  EEPopUpForeColor, EEPopUpXorColor,
                                  EEWindowsFrameWidth, &Cursor,
                                  INTR_WNDW_PLACE_CENTER);
                }
            }
	    break;
    	case 1: /* Free Mem. */
    	    PrintMemoryFree();
    	    break;
    	case 2: /* Get zoom factor. */
    	    sprintf(Line, "Current Zoom factor is %2.5lf",
    	            pow(2.0, (double) (IntrWndwGetZoomFactor(ActiveWindowID) -
				       DEFAULT_ZOOM_FACTOR)));
	    IntrQueryContinue(Line, EEPopUpFrameColor, EEPopUpBackColor,
                              EEPopUpForeColor, EEPopUpXorColor,
                              EEWindowsFrameWidth, &Cursor,
                              INTR_WNDW_PLACE_CENTER);
    	    break;
    	case 3: /* Draw Text */
    	    i = GRDrawText;
    	    GRDrawText = IntrQueryYesNo("Draw text?", EEPopUpFrameColor,
    					EEPopUpBackColor, EEPopUpForeColor,
    					EEPopUpXorColor, EEWindowsFrameWidth,
                                        &Cursor, INTR_WNDW_PLACE_CENTER);
    	    if (i != GRDrawText)
    		RedrawAllWindows();
    	    break;
    	case 4: /* Text Scale */
    	    sprintf(Line, "%d", EETextScale);
    	    IntrQueryLine("Text Scale size [1..7]:", Line,
			  LINE_LEN_SHORT - 1, EEPopUpFrameColor,
                          EEPopUpBackColor, EEPopUpForeColor,
                          EEWindowsFrameWidth, INTR_WNDW_PLACE_CENTER);
    	    if (sscanf(Line, "%d", &i) != 1 || i < 1 || i > 7)
    		IntrQueryContinue("Wrong format/range, ignored",
    				  EEPopUpFrameColor, EEPopUpBackColor,
                                  EEPopUpForeColor, EEPopUpXorColor,
                                  EEWindowsFrameWidth, &Cursor,
                                  INTR_WNDW_PLACE_CENTER);
    	    else
    		EETextScale = i;
	    break;
    	case 5: /* Set auto pan */
    	    EEAutoPan =
		    IntrQueryYesNo("Enable automatic panning?",
				   EEPopUpFrameColor, EEPopUpBackColor,
                                   EEPopUpForeColor, EEPopUpXorColor,
                                   EEWindowsFrameWidth, &Cursor,
                                   INTR_WNDW_PLACE_CENTER);
    	    break;
    	case 6: /* Vert. Horiz. Lines */
    	    EEHVLineDrawing =
		    IntrQueryYesNo("Draw only vertical/horizontal lines?",
				   EEPopUpFrameColor, EEPopUpBackColor,
                                   EEPopUpForeColor, EEPopUpXorColor,
                                   EEWindowsFrameWidth, &Cursor,
                                   INTR_WNDW_PLACE_CENTER);
    	    break;
    	case 7: /* Snap Factor */
    	    sprintf(Line, "%d", EESnapDistance);
    	    IntrQueryLine("New snap factor [0..1024]:", Line,
			  LINE_LEN_SHORT - 1, EEPopUpFrameColor,
                          EEPopUpBackColor, EEPopUpForeColor,
                          EEWindowsFrameWidth, INTR_WNDW_PLACE_CENTER);
    	    if (sscanf(Line, "%d", &i) != 1 || i < 1 || i > 1024)
    		IntrQueryContinue("Wrong format/range, ignored",
                    		  EEPopUpFrameColor, EEPopUpBackColor,
                                  EEPopUpForeColor, EEPopUpXorColor,
                                  EEWindowsFrameWidth, &Cursor,
                                  INTR_WNDW_PLACE_CENTER);
    	    else
    		EESnapDistance = i;
    	    break;
    	case 8: /* Draw Line Width */
    	    sprintf(Line, "%d", ReturnCurrentWidth());
    	    IntrQueryLine("Set New Line Width [0..50]:", Line,
			  LINE_LEN_SHORT - 1, EEPopUpFrameColor,
                          EEPopUpBackColor, EEPopUpForeColor,
                          EEWindowsFrameWidth, INTR_WNDW_PLACE_CENTER);
    	    if (sscanf(Line, "%d", &i) != 1 || i < 1 || i > 50)
    		IntrQueryContinue("Wrong range, ignored",
                    		  EEPopUpFrameColor, EEPopUpBackColor,
                                  EEPopUpForeColor, EEPopUpXorColor,
                                  EEWindowsFrameWidth, &Cursor,
                                  INTR_WNDW_PLACE_CENTER);
    	    else
    		SetCurrentWidth(i);
    	    break;
    }
}

/*****************************************************************************
* Given a full path file name returns a pointer to the file name only.	     *
*****************************************************************************/
static char *GetFileName(char *FullPathName)
{
    int i = strlen(FullPathName) - 1;

    while (i >= 0 && FullPathName[i] != '\\' &&
    		     FullPathName[i] != '/' &&
		     FullPathName[i] != ':') i--;
    return i > 0 ? &FullPathName[i + 1] : FullPathName;
}

/*****************************************************************************
* Routine to refresh root window drawing.				     *
*****************************************************************************/
static void RootWndwRefreshFunc(int WindowID)
{
    IntrBBoxStruct *BBox = IntrWndwGetBBox(WindowID);
    int x = (BBox -> Xmax - BBox -> Xmin) / 2,
        y = (BBox -> Ymax - BBox -> Ymin) / 3;

    GRSetTextJustify(GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER);

    GRSetSTextStyle(GRFontName, GR_HORIZ_DIR, 8);

    IntrAllocColor(EERootWndwForeColor, INTR_INTENSITY_HIGH);
    GRSText(x + 8, y + 8, "EEdraw");
    IntrAllocColor(EERootWndwForeColor, INTR_INTENSITY_VHIGH);
    GRSText(x, y, "EEdraw");

    GRSetSTextStyle(GRFontName, GR_HORIZ_DIR, 2);

    y = y + 50;
    IntrAllocColor(EERootWndwForeColor, INTR_INTENSITY_HIGH);
    GRSText(x + 2, y + 2, "(c) Copyright 1989-91 Gershon Elber");
    IntrAllocColor(EERootWndwForeColor, INTR_INTENSITY_VHIGH);
    GRSText(x, y, "(c) Copyright 1989-91 Gershon Elber");

    y = y * 2;
    IntrAllocColor(EERootWndwForeColor, INTR_INTENSITY_HIGH);
    GRSText(x + 2, y + 2, "& Peter Cooper 1992- for Ver 2.4");
    IntrAllocColor(EERootWndwForeColor, INTR_INTENSITY_VHIGH);
    GRSText(x, y, "& Peter Cooper 1992- for Ver 2.4");

    IntrWndwSetRefreshFunc(WindowID, NULL);    /* Disable further refreshes. */
}

/*****************************************************************************
* Routine to refresh Layer window drawing.				     *
*****************************************************************************/
static void LayerWndwRefreshFunc(int WindowID)
{
/*    IntrBBoxStruct *BBox = IntrWndwGetBBox(WindowID);
    int x = (BBox -> Xmax - BBox -> Xmin) / 2,
        y = (BBox -> Ymax - BBox -> Ymin) / 3;

    GRSetTextJustify(GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER);

    GRSetSTextStyle(GRFontName, GR_HORIZ_DIR, 8);

    IntrAllocColor(EERootWndwForeColor, INTR_INTENSITY_HIGH);
  */ 
    
}
/*****************************************************************************
* Routine to refresh help window drawing.				     *
*****************************************************************************/
static void HelpWndwRefreshFunc(int WindowID)
{
    IntrTextWndwRefresh(WindowID);
}

/*****************************************************************************
* Routine to refresh root window drawing.				     *
*****************************************************************************/
static void DataWndwRefreshFunc(int WindowID)
{
    int i, x, y;
    IntrBType IsVertical;
    IntrRType Zoom, Value, XFrac, YFrac;
    EEWindowStruct *TmpWndw,
        *Window = NULL;
    IntrBBoxStruct *BBox;

    /* First do the most likely thing... */
    if (WindowID == EEActiveWindow -> IntrLibWindowID)
	Window = EEActiveWindow;
    else {
	for (Window = EEWindowsList; Window != NULL; Window = Window -> Pnext)
	    if (WindowID == Window -> IntrLibWindowID)
                break;
    }

    if (Window == NULL) IntrFatalError("Wrong Window ID.");

    /* Update the scroll bars. */
    i = IntrWndwGetZoomFactor(Window -> IntrLibWindowID) - DEFAULT_ZOOM_FACTOR;
    if (i > 0)
	Zoom = 1 << i;
    else if (i < 0)
	Zoom = 1.0 / (1 << (-i));
    else
	Zoom = 1.0;
    BBox = IntrWndwGetBBox(Window -> IntrLibWindowID);
    XFrac = (BBox -> Xmax - BBox -> Xmin) /
            (Window -> PageXSize * Zoom + (BOUNDARY_WIDTH << 1));
    YFrac = (BBox -> Ymax - BBox -> Ymin) /
       	    (Window -> PageYSize * Zoom + (BOUNDARY_WIDTH << 1));

    if (IntrWndwIsScrollBarEvent(Window -> IntrLibWindowID, &IsVertical,
    								    &Value)) {
	/* This refresh is a result of a scroll bar event on the window. */
	IntrWndwGetPanFactors(Window -> IntrLibWindowID, &x, &y);
        if (IsVertical) {
	    if (YFrac > 1.0)
		y = DEFAULT_INV_ZOOM(Window -> PageYSize) / 2;
            else {
		Value = Value + YFrac / 2.0;
		if (Value > 1.0 - YFrac / 2.0) Value = 1.0 - YFrac / 2.0;
		y = Value * DEFAULT_INV_ZOOM(Window -> PageYSize);
            }
        }
        else {
	    if (XFrac > 1.0)
		x = DEFAULT_INV_ZOOM(Window -> PageXSize) / 2;
            else {
		Value = Value + XFrac / 2.0;
		if (Value > 1.0 - XFrac / 2.0) Value = 1.0 - XFrac / 2.0;
		x = Value * DEFAULT_INV_ZOOM(Window -> PageXSize);
	    }
        }
	IntrWndwSetPanning(Window -> IntrLibWindowID, x, y);
        GRSetPanFactors(x, y);
    }

    IntrWndwGetPanFactors(Window -> IntrLibWindowID, &x, &y);
    if (XFrac >= 1.0)
	IntrWndwUpdateScrollBar(Window -> IntrLibWindowID, FALSE, 0.0, 1.0);
    else
        IntrWndwUpdateScrollBar(Window -> IntrLibWindowID, FALSE,
	    x / ((IntrRType) DEFAULT_INV_ZOOM(Window -> PageXSize)) -
                XFrac / 2.0,
	    XFrac);
    if (YFrac >= 1.0)
	IntrWndwUpdateScrollBar(Window -> IntrLibWindowID, TRUE, 0.0, 1.0);
    else
	IntrWndwUpdateScrollBar(Window -> IntrLibWindowID, TRUE,
	    y / ((IntrRType) DEFAULT_INV_ZOOM(Window -> PageYSize)) -
                YFrac / 2.0,
	    YFrac);

    /* Redraw the window content. */
    TmpWndw = EEActiveWindow;	/* Save current active window pointer */
    EEActiveWindow = Window;	/* set up pointer for Layer Drawing */

    RedrawStructList(Window -> EEDrawList, GR_COPY_PUT, EE_DRAW_COLOR);
    EEActiveWindow = TmpWndw;	/* restore Main Active Window Pointer */

    /* Draw the window page border. */
    GRSetWriteMode(GR_COPY_PUT);
    IntrAllocColor(EEHighLightColor, INTR_INTENSITY_VHIGH);
    GRSetLineStyle(GR_SOLID_LINE, 0, GR_THICK_WIDTH);
    GRMoveTo(0, 0);
    GRLineTo(0, DEFAULT_INV_ZOOM(Window -> PageYSize));
    GRLineTo(DEFAULT_INV_ZOOM(Window -> PageXSize),
    				       DEFAULT_INV_ZOOM(Window -> PageYSize));
    GRLineTo(DEFAULT_INV_ZOOM(Window -> PageXSize), 0);
    GRLineTo(0, 0);
    GRSetLineStyle(GR_SOLID_LINE, 0, GR_NORM_WIDTH);
}

/*****************************************************************************
* Routine to handle key bindings.					     *
*****************************************************************************/
static void HandleSameAgain(int KeyStroke)
{
    HandleKeyBindings(LastKeyStroke);
}

/*****************************************************************************
* Routine to handle key bindings.					     *
*****************************************************************************/
static void HandleKeyBindings(int KeyStroke)
{
    int i;

    LastKeyStroke = KeyStroke;

    for (i = 0; i < KeyBindingCount; i++)
	if (KeyBindingList[i].ScanCode == KeyStroke) {
	    /* Activate the related function. */
	    PDActionFuncs[KeyBindingList[i].Menu](KeyBindingList[i].MenuEntry -
						     DIRECT_CALL_INDEX_OFFSET);
	    break;
        }
}

/*****************************************************************************
* Routine to read the key binding file if such exists.			     *
*****************************************************************************/
static BooleanType ReadKeyBindings(char *Name)
{
    int i, j, Len, ScanCode,
	LineNum = 0;
    IntrBType FuncFound;
    FILE *f;
    char Buffer[LINE_LEN_SHORT], *FunctionName,	*KeyName, *ScanCodeStr, *p;

    strcpy(Buffer, Name);		    /* Remove old type if has one... */
    if ((p = strrchr(Buffer, '.')) != NULL) *p = 0;
    strcat(Buffer, ".BND");	       /* ... and add the binding file type. */

    /* Search in path, and if fails, return silently: */
    p = searchpath(Buffer);
    if (p == NULL || (f = fopen(p, "rt")) == NULL) return TRUE;

    while (fgets(Buffer, LINE_LEN_SHORT - 1, f)) {
	LineNum++;
	if (Buffer[0] == ';' || Buffer[0] == '\n' || Buffer[0] == '\r')
	    continue;

	if ((FunctionName = strtok(Buffer, " \t\n\r")) == NULL ||
	    (KeyName = strtok(NULL, " \t\n\r")) == NULL ||
	    (ScanCodeStr = strtok(NULL, " \t\n\r")) == NULL ||
	    sscanf(ScanCodeStr, "%d", &ScanCode) != 1) {
	    fprintf(stderr, "Wrong format, binding file \"%s\", line %d.\n",
								p, LineNum);
	    fclose(f);
	    return FALSE;
	}

	Len = strlen(FunctionName);
	FuncFound = FALSE;
        if (strncmp("SameAgain", FunctionName, Len) == 0) {
	    IntrRegisterKeyStroke(ScanCode, HandleSameAgain);
            FuncFound = TRUE;
        }
	else
	    for (i = 0; !FuncFound && i < ALL_POP_UP_SIZE; i++)
	        for (j = 0; !FuncFound && j < AllPUSizes[i]; j++)
		    if (strncmp(AllPUStrs[i][j], FunctionName, Len) == 0 &&
		        KeyBindingCount < MAX_KEY_BINDINGS) {
		        KeyBindingList[KeyBindingCount].ScanCode = ScanCode;
                        KeyBindingList[KeyBindingCount].Menu = i;
                        KeyBindingList[KeyBindingCount++].MenuEntry = j;
		        IntrRegisterKeyStroke(ScanCode, HandleKeyBindings);
		        if (strlen(KeyName) > 4) KeyName[4] = 0;
	                Len = strlen(AllPUStrs[i][j]) - strlen(KeyName) - 2;
		        sprintf(&AllPUStrs[i][j][Len], "[%s]", KeyName);
                        FuncFound = TRUE;
		    }
	if (!FuncFound) {
	    fprintf(stderr,
		"No such function as \"%s\", binding file \"%s\", line %d.\n",
						FunctionName, p, LineNum);
	    fclose(f);
	    return FALSE;
	}
    }

    fclose(f);

    return TRUE;
}

/*****************************************************************************
* My Routine to	allocate dynamic memory. All program requests must call this *
* routine (no direct call to malloc). Dies if no memory.		     *
*****************************************************************************/
VoidPtr MyMalloc(unsigned size)
{
    static int Unlocked = TRUE;
    static time_t LastTime = 0;
    char *p;
    time_t CrntTime;


#ifdef DEBUG_MALLOC_TC20
    unsigned int *i;

    size += 6;
#endif /* DEBUG_MALLOC_TC20 */

    p = malloc(size);
    if (p == NULL)
	FatalError("Not enough memory, exit\n");
    if (Unlocked && coreleft() < 32768L) {
	/* Unlocked is used to make sure we would not recurse from the below */
	/* Routines when it calls MyMalloc - this may cause infinite loop... */
	Unlocked = FALSE;

	time(&CrntTime);
	if (CrntTime - LastTime > 30) {    /* Let user know every 30 second. */
	    IntrQueryContinue("Free memory too small - dangerous to continue",
                    	      EEPopUpFrameColor, EEPopUpBackColor,
                              EEPopUpForeColor, EEPopUpXorColor,
                              EEWindowsFrameWidth, &Cursor,
                              INTR_WNDW_PLACE_CENTER);
	    LastTime = CrntTime;
	}
	Unlocked = TRUE;
    }

#ifdef DEBUG_MALLOC_TC20
    /* Do the following tests on the memory allocated:			     */
    /* 1. Uses TC 2.0 heuristic to make sure pointer are legal by comparing  */
    /*    their offset to the constant 8.				     */
    /* 2. Mark the end of allocated memory for over written test in MyFree.  */
    if (FP_OFF(p) != 8) {
	GetContinueQuestion(
	    "Bogus pointer detected - unsafe to continue. Report it as 1.",
	    CENTER_CENTER);
    }
    strcpy(&p[size-4], "ILG");			 /* Put a marker at the end. */
    i = (unsigned int *) p;    /* Save size of this block at the begging and */
    *i = size;				  /* return a pointer just after it. */
    p += 2;
#endif /* DEBUG_MALLOC_TC20 */

    return p;
}

/*****************************************************************************
* My Routine to	free dynamic memory. All program requests must call this     *
* routine (no direct call free).					     *
*****************************************************************************/
void MyFree(VoidPtr p)
{
#ifdef DEBUG_MALLOC_TC20
    char *pc = (char *) p;
    unsigned int *i, size;

    /* Do the following tests on the memory allocated.			     */
    /* 1. Uses TC 2.0 heuristic to make sure pointer are legal by comparing  */
    /*    their offset to constant 8 (+2 as we skip the size we entered).    */
    /* 2. Test the mark at the end of the allocated memory for over written. */
    if (FP_OFF(p) != 8 + 2) {
	GetContinueQuestion(
	    "Bogus pointer detected - unsafe to continue. Report it as 2.",
	    CENTER_CENTER);
	return;
    }
    pc -= 2;
    i = (unsigned int *) pc;
    size = *i;
    if (strcmp(&pc[size-4], "ILG") != 0) {
	GetContinueQuestion(
	    "Overwritten pointer detected - unsafe to continue. Report it as 3.",
	    CENTER_CENTER);
	return;
    }
    p = pc;
#endif /* DEBUG_MALLOC_TC20 */

#ifdef DEBUG_MALLOC_TCPP
    int i = heapchecknode(p);

    switch(heapchecknode(p)) {
	case _HEAPEMPTY:
	case _HEAPCORRUPT:
	case _BADNODE:
	case _FREEENTRY:
	GetContinueQuestion(
	    "Bogus pointer detected - unsafe to continue. Report it as 4.",
	    CENTER_CENTER);
	    return;
    }
#endif /* DEBUG_MALLOC_TCPP */

    free(p);
}

#ifdef DEBUG_MALLOC_TC20

/*****************************************************************************
* Define local strdup as we offset the pointers by 2 to save the size and    *
* calling to MyFree with pointers allocated via strdup will result with a    *
* fatal error...							     *
*****************************************************************************/
char *strdup(const char *Str)
{
    char *NewStr = (char *) MyMalloc(strlen(Str) + 1);

    strcpy(NewStr, Str);

    return NewStr;
}

#endif /* DEBUG_MALLOC_TC20 */

/*****************************************************************************
* MyExit routine. Note it might call to CloseGraph without calling	     *
* InitGraph(), or call MouseClose() without MouseInit() etc. and it is the   *
* responsibility of the individual modules to do nothing in these cases.     *
*****************************************************************************/
void MyExit(int ExitCode)
{
    IntrClose();			   /* Close the interaction library. */

    RestoreCtrlBrk();

    ChangeDir(InitialPath);

    exit(ExitCode);
}

/*****************************************************************************
* Same as MyExit routine, but print error message to stderr.		     *
*****************************************************************************/
void FatalError(char *ErrMsg)
{
    IntrClose();			   /* Close the interaction library. */

    fprintf(stderr, "EEDRAW: %s\n", ErrMsg);

    RestoreCtrlBrk();

    ChangeDir(InitialPath);

    exit('F');
}
