/*****************************************************************************
*   Module to handle libraries (second part - drawing and interaction).	     *
*									     *
* Written by:  Gershon Elber			IBM PC Ver 1.0,	Oct. 1989    *
*****************************************************************************/

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <dos.h>
#include <dir.h>
#include <alloc.h>
#include <time.h>
#include "Program.h"
#include "Director.h"
#include "PriorQue.h"
#include "EELibs.h"
#include "EELibsL.h"
#include "EECreate.h"
#include "EELoad.h"
#include "EEModify.h"
#include "EERedraw.h"
#include "EEString.h"
#include "EELayer.h"
#include "Primary.h"

/* Used the hold cursor information for local cursor drawing routines. */
static DrawLibItemStruct *CrsrDrawLibItem;
static LibraryEntryStruct *CrsrLibEntry;
static IntrCursorShapeStruct Cursor = {
    INTR_CURSOR_ARROW, 0, 0, 0, 0, FALSE, NULL, FALSE
};

static char *TransformStrs[] =
{
    "PlaceIt",
    "",
    "RotateR",
    "RotateL",
    "MirrorX",
    "MirrorY",
};
#define TRANS_MENU_SIZE (sizeof(TransformStrs) / sizeof(char *))

static IntrPopUpMenuStruct
    *TransPopUpMenu = NULL;

static void DrawLibPartAux(LibraryEntryStruct *Entry, int PartX, int PartY,
	int TransMat[2][2], int Multi, int DrawMode, int Mode);
static void PushNetListItem(NetListStruct **NetList,
			    int MapX1, int MapY1, int MapX2, int MapY2,
			    char *PartName, char *ChipName, char *PinName,
			    int PinNum);
static char *LookUpPinText(char *Pins, int PinNum);
static void MapAngles(int *Angle1, int *Angle2, int TransMat[2][2]);
static void ViewOneLibrary(LibraryStruct *Lib);
static LibraryEntryStruct *FindLibPart(char *Name);
static void DrawingEntryCursor(int x, int y);

/*****************************************************************************
* Routine to view library(ies) content.					     *
*****************************************************************************/
void ViewLibrary(void)
{
    int i, NumOfLibs = NumOfLibraries();
    char **Names;
    LibraryStruct *Lib;

    Cursor.CursorType = INTR_CURSOR_ARROW;

    if (NumOfLibs == 0) {
	IntrQueryContinue("No libraries are loaded", EEPopUpFrameColor,
        		  EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
                          EEWindowsFrameWidth, &Cursor,
                          INTR_WNDW_PLACE_CENTER);

	return;
    }
    Names = (char **) MyMalloc(sizeof(char *) * NumOfLibs);
    for (i = 0, Lib = LibraryList; Lib != NULL; Lib = Lib -> Pnext, i++) {
	Names[i] = Lib -> Name;
    }
    do {
	i = IntrQueryList("View Libs", (char **) Names, 0, NumOfLibs,
			  EEListNumDisplayed, EEPopUpFrameColor,
                          EEPopUpBackColor, EEPopUpForeColor,
                          EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
                          INTR_WNDW_PLACE_CENTER);
	if (i >= 0) {
            IntrWndwPop(EERootWindowID, TRUE, FALSE);

	    for (Lib = LibraryList; i > 0; i--, Lib = Lib -> Pnext);
	    ViewOneLibrary(Lib);

            IntrWndwPush(EERootWindowID, TRUE);
	}
    }
    while (i >= 0);

    MyFree((VoidPtr) Names);
}

/*****************************************************************************
* Routine to draw the given part at given position, transformed/mirror as    *
* specified, and in the given drawing mode. Only this one is visible...	     *
*****************************************************************************/
void DrawLibPart(DrawLibItemStruct *DrawLibItem, int DrawMode, int Color)
{
    LibraryEntryStruct *Entry;
    char Line[LINE_LEN];

    GRSetLineStyle(GR_SOLID_LINE, 0, GR_NORM_WIDTH);

    Cursor.CursorType = INTR_CURSOR_ARROW;

    if ((Entry = FindLibPart(DrawLibItem -> ChipName)) == NULL) {
	sprintf(Line, "Failed to find part \"%s\" in library",
						DrawLibItem -> ChipName);
	IntrQueryContinue(Line, EEPopUpFrameColor,
        		  EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
                          EEWindowsFrameWidth, &Cursor,
                          INTR_WNDW_PLACE_CENTER);
	return;
    }
    if(Color==EE_ERASE_COLOR)
    	DrawLibPartAux(Entry,
		   DrawLibItem -> PosX,
		   DrawLibItem -> PosY,
		   DrawLibItem -> Transform,
		   DrawLibItem -> Multi,
		   DrawMode,
		   0);
    else
    	DrawLibPartAux(Entry,
		   DrawLibItem -> PosX,
		   DrawLibItem -> PosY,
		   DrawLibItem -> Transform,
		   DrawLibItem -> Multi,
		   DrawMode,
		   1);

    if (Entry -> DrawName &&
	DrawLibItem -> ChipNameOrient != TEXT_ORIENT_NON){
	if((ReturnLayerMode(LAYER_DEVICE) & 0x03) && Color!=EE_ERASE_COLOR)
		GRSetColor(ReturnLayerColor(LAYER_DEVICE));
	else
		GRSetColor(EE_ERASE_COLOR);

	PutTextInfo(DrawLibItem -> ChipNameOrient,
	    	DrawLibItem -> ChipNameX,
	    	DrawLibItem -> ChipNameY,
	    	1,
	     	DrawLibItem -> ChipName); 
		
	
    }
    if (DrawLibItem -> PartNameOrient != TEXT_ORIENT_NON){
	if((ReturnLayerMode(LAYER_REFDES) & 0x03) && Color!=EE_ERASE_COLOR)
		GRSetColor(ReturnLayerColor(LAYER_REFDES));
	else
		GRSetColor(EE_ERASE_COLOR);
	 
	PutTextInfo(DrawLibItem -> PartNameOrient,
	    	DrawLibItem -> PartNameX,
	    	DrawLibItem -> PartNameY,
	    	1,
	    	DrawLibItem -> PartName); 
	
    }
}

/*****************************************************************************
* Routine to clear the given part at given position,                         *
*****************************************************************************/
void DrawLibPartClear(DrawLibItemStruct *DrawLibItem, int DrawMode)
{
    LibraryEntryStruct *Entry;
    
    char Line[LINE_LEN];

    GRSetLineStyle(GR_SOLID_LINE, 0, GR_NORM_WIDTH);

    Cursor.CursorType = INTR_CURSOR_ARROW;

    if ((Entry = FindLibPart(DrawLibItem -> ChipName)) == NULL) {
	sprintf(Line, "Failed to find part \"%s\" in library",
						DrawLibItem -> ChipName);
	IntrQueryContinue(Line, EEPopUpFrameColor,
        		  EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
                          EEWindowsFrameWidth, &Cursor,
                          INTR_WNDW_PLACE_CENTER);
	return;
    }
    
   DrawLibPartAux(Entry,
	   DrawLibItem -> PosX,
	   DrawLibItem -> PosY,
	   DrawLibItem -> Transform,
	   DrawLibItem -> Multi,
	   DrawMode,
	   0);


    if (Entry -> DrawName &&
	DrawLibItem -> ChipNameOrient != TEXT_ORIENT_NON){
	GRSetColor(EE_ERASE_COLOR);
	PutTextInfo(DrawLibItem -> ChipNameOrient,
	    	DrawLibItem -> ChipNameX,
	    	DrawLibItem -> ChipNameY,
	    	1,
	    	DrawLibItem -> ChipName);
	
    }
    if (DrawLibItem -> PartNameOrient != TEXT_ORIENT_NON){
	GRSetColor(EE_ERASE_COLOR);
	PutTextInfo(DrawLibItem -> PartNameOrient,
	    	DrawLibItem -> PartNameX,
	    	DrawLibItem -> PartNameY,
	    	1,
	    	DrawLibItem -> PartName);
	
    }
}
/*****************************************************************************
* Routine to find a part in one of the libraries given its name.	     *
*****************************************************************************/
static LibraryEntryStruct *FindLibPart(char *Name)
{
    LibraryEntryStruct *Entry, DummyEntry;
    LibraryStruct
	*Lib = LibraryList;

    DummyEntry.Pins = NULL;			/* Used only to call PQFind. */
    DummyEntry.Drawings = NULL;
    DummyEntry.Multi = NULL;
    strcpy(DummyEntry.Name, Name);

    PQCompFunc((PQCompFuncType) LibraryEntryCompare);

    while (Lib) {
	if ((Entry = PQFind(Lib -> Entries, &DummyEntry)) != NULL)
	    return Entry;

	Lib = Lib -> Pnext;
    }
    return NULL;
}

/*****************************************************************************
* Routine to draw the given part at given position, transformed/mirror as    *
* specified, and in the given drawing mode.				     *
*****************************************************************************/
static void DrawLibPartAux(LibraryEntryStruct *Entry, int PartX, int PartY,
	int TransMat[2][2], int Multi, int DrawMode, int Mode)
/* Mode 0=EE_ERASE_COLOR, Mode 1=LAYER_COLOR */
{
    int i, x1, y1, x2, y2, IsMulti, *NextPinMulti, NextPinNum, t1, t2,
	y, MapX1, MapY1, MapX2, MapY2, PinWidth, *Poly;
    char Line[LINE_LEN], *NextPinText;
    LibraryDrawEntryStruct *DEntry;

    /* GRSetFillStyle(GR_SOLID_FILL, Color); */
    GRSetWriteMode(DrawMode);
    
    IsMulti = Entry -> NumOfUnits > 0;
    if (IsMulti) {
	/* Make NextMulti point on next pin number in multi array: */
	NextPinMulti = &Entry -> Multi[Entry -> PinsPerUnit * --Multi];

	NextPinText = NULL;
    }
    else {
	NextPinNum = 1;
	NextPinMulti = NULL;

	/* Make a copy of all pin text info so we can use strtok routine on: */
	strncpy(Line, Entry -> Pins, LINE_LEN - 1);
	NextPinText = strtok(Line, PIN_SEPERATOR);
    }

    if (Entry -> Drawings != NULL) {
	DEntry = Entry -> Drawings;
	while (DEntry != NULL) {
	    switch (DEntry -> DrawType) {
		case ARC_DRAW_TYPE:
		    
		    if((!(ReturnLayerMode(DEntry -> Layer) & 0x03)) & (Mode==1)) 			break;
		    else if(Mode==0)
			GRSetColor(EE_ERASE_COLOR);
		    else
			GRSetColor(ReturnLayerColor(DEntry -> Layer));
		    t1 = DEntry -> U.Arc.t1;
		    t2 = DEntry -> U.Arc.t2;
		    MapAngles(&t1, &t2, TransMat);
		    GRArc(PartX + TransMat[0][0] * DEntry -> U.Arc.x +
				  TransMat[0][1] * DEntry -> U.Arc.y,
			  PartY + TransMat[1][0] * DEntry -> U.Arc.x +
				  TransMat[1][1] * DEntry -> U.Arc.y,
			  t1,
			  t2,
			  DEntry -> U.Arc.r);
		    break;
		case CIRCLE_DRAW_TYPE:
		    if((!(ReturnLayerMode(DEntry -> Layer) & 0x03)) & (Mode==1))

			break;
		    else if(Mode==0)
			GRSetColor(EE_ERASE_COLOR);
		    else
			GRSetColor(ReturnLayerColor(DEntry -> Layer));
		    GRCircle(PartX + TransMat[0][0] * DEntry -> U.Circ.x +
				     TransMat[0][1] * DEntry -> U.Circ.y,
			     PartY + TransMat[1][0] * DEntry -> U.Circ.x +
				     TransMat[1][1] * DEntry -> U.Circ.y,
			     DEntry -> U.Circ.r);
		    break;
		case TEXT_DRAW_TYPE:
		    
		    if((!(ReturnLayerMode(DEntry -> Layer) & 0x03)) & (Mode==1))

			break;
		    else if(Mode==0)
			GRSetColor(EE_ERASE_COLOR);
		    else
			GRSetColor(ReturnLayerColor(DEntry -> Layer));
		    /* The text orientation may need to be flipped if the    */
		    /* transformation matrix cuases xy axes to be flipped.   */
		    t1 = (TransMat[0][0] == 0) ^ (DEntry -> U.Text.Horiz != 0);
		    x1 = PartX + TransMat[0][0] * DEntry -> U.Text.x
			       + TransMat[0][1] * DEntry -> U.Text.y;
		    y1 = PartY + TransMat[1][0] * DEntry -> U.Text.x
			       + TransMat[1][1] * DEntry -> U.Text.y;
		    PutTextInfo(t1 ? GR_HORIZ_DIR : GR_VERT_DIR, x1, y1, 1,
				DEntry -> U.Text.Text);
		    break;
		case SQUARE_DRAW_TYPE:
		    
		    if((!(ReturnLayerMode(DEntry -> Layer) & 0x03)) & (Mode==1))

			break;
		    else if(Mode==0)
			GRSetColor(EE_ERASE_COLOR);
		    else
			GRSetColor(ReturnLayerColor(DEntry -> Layer));
		    x1 = PartX + TransMat[0][0] * DEntry -> U.Sqr.x1
			       + TransMat[0][1] * DEntry -> U.Sqr.y1;
		    y1 = PartY + TransMat[1][0] * DEntry -> U.Sqr.x1
			       + TransMat[1][1] * DEntry -> U.Sqr.y1;
		    x2 = PartX + TransMat[0][0] * DEntry -> U.Sqr.x2
			       + TransMat[0][1] * DEntry -> U.Sqr.y2;
		    y2 = PartY + TransMat[1][0] * DEntry -> U.Sqr.x2
			       + TransMat[1][1] * DEntry -> U.Sqr.y2;
		    GRMoveTo(x1, y1);
		    GRLineTo(x1, y2);
		    GRLineTo(x2, y2);
		    GRLineTo(x2, y1);
		    GRLineTo(x1, y1);
		    break;
		case LINE_DRAW_TYPE:
		    
		    if((!(ReturnLayerMode(DEntry -> Layer) & 0x03)) & (Mode==1)) 			break;
		    else if(Mode==0)
			GRSetColor(EE_ERASE_COLOR);
		    else
			GRSetColor(ReturnLayerColor(DEntry -> Layer));
		    x1 = PartX + TransMat[0][0] * DEntry -> U.Line.x1
			       + TransMat[0][1] * DEntry -> U.Line.y1;
		    y1 = PartY + TransMat[1][0] * DEntry -> U.Line.x1
			       + TransMat[1][1] * DEntry -> U.Line.y1;
		    x2 = PartX + TransMat[0][0] * DEntry -> U.Line.x2
			       + TransMat[0][1] * DEntry -> U.Line.y2;
		    y2 = PartY + TransMat[1][0] * DEntry -> U.Line.x2
			       + TransMat[1][1] * DEntry -> U.Line.y2;
		    if (DEntry -> U.Line.Invert) {
			MapX1 = SIGN(x2 - x1);
			MapY1 = SIGN(y2 - y1);
			GRCircle(MapX1 * INVERT_PIN_RADIUS + x1,
				 MapY1 * INVERT_PIN_RADIUS + y1,
				 INVERT_PIN_RADIUS);
			GRMoveTo(MapX1 * INVERT_PIN_RADIUS * 2 + x1,
				 MapY1 * INVERT_PIN_RADIUS * 2 + y1);
			GRLineTo(x2, y2);
		    }
		    else {
			GRMoveTo(x1, y1);
			GRLineTo(x2, y2);
		    }
		    
		    if(Mode==0)
			GRSetColor(EE_ERASE_COLOR);
		    else
			GRSetColor(ReturnLayerColor(LAYER_PIN));
		    if(ReturnLayerMode(LAYER_PIN))
		    	GRCircle(x2,y2,3);
		    
		    if((!(ReturnLayerMode(DEntry -> Layer) & 0x03)) & (Mode==1)) 			break;
		    else if(Mode==0)
			GRSetColor(EE_ERASE_COLOR);
		    else
			GRSetColor(ReturnLayerColor(DEntry -> Layer));
		    if (IsMulti) {
			PutLineTextInfo(x1, y1, x2, y2,
			    LookUpPinText(Entry -> Pins, *NextPinMulti),
			    *NextPinMulti,
			    Entry -> TextInside,
			    Entry -> DrawNums,Mode);
			NextPinMulti++;
		    }
		    else {
			PutLineTextInfo(x1, y1, x2, y2,
			    NextPinText,
			    NextPinNum,
			    Entry -> TextInside,
			    Entry -> DrawNums,Mode);
			NextPinText = strtok(NULL, PIN_SEPERATOR);
			NextPinNum++;
		    }
		    break;
		case POLYLINE_DRAW_TYPE:
		    
		    if((!(ReturnLayerMode(DEntry -> Layer) & 0x03)) & (Mode==1))

			break;
		    else if(Mode==0)
			GRSetColor(EE_ERASE_COLOR);
		    else
			GRSetColor(ReturnLayerColor(DEntry -> Layer));
		    Poly = (int *) MyMalloc(sizeof(int) * 2 *
							DEntry -> U.Poly.n);
		    for (i = 0; i < DEntry -> U.Poly.n; i++) {
			Poly[i * 2] = PartX +
			    TransMat[0][0] * DEntry -> U.Poly.PolyList[i * 2] +
			    TransMat[0][1] * DEntry -> U.Poly.PolyList[i * 2 + 1];
			Poly[i * 2 + 1] = PartY +
			    TransMat[1][0] * DEntry -> U.Poly.PolyList[i * 2] +
			    TransMat[1][1] * DEntry -> U.Poly.PolyList[i * 2 + 1];
		    }
		if(Mode==1)
   		    GRSetFillStyle(GR_SOLID_FILL,
			 ReturnLayerColor(DEntry->Layer));
		else
		    GRSetFillStyle(GR_SOLID_FILL,EE_ERASE_COLOR);
		    GRPoly(DEntry -> U.Poly.n, Poly, DEntry -> U.Poly.Fill);
		    MyFree((VoidPtr) Poly);
		    break;
	    }
	    DEntry = DEntry -> Pnext;
	}
    }
    else {		  /* NULL Drawing - draw simple a box with all pins: */
	y1 = Entry -> TextInside ? PIN_WIDTH * Entry -> NumOfPins / 4 :
				   PIN_WIDTH * Entry -> NumOfPins / 2;
	x1 = Entry -> TextInside ? (int) (y1 * CHIP_BOX_ASPECT_TI) :
				   (int) (y1 * CHIP_BOX_ASPECT_TO);
	/* But make sure we can still print somethings inside... */
	if (x1 < DRAW_TEXT_WIDTH * 12) x1 = DRAW_TEXT_WIDTH * 12;
	x2 = x1 / 2;
	y2 = y1 / 2;
	x1 = -x2;
	y1 = -y2;
	PinWidth = Entry -> TextInside ? PIN_WIDTH / 2 : PIN_WIDTH;

/* Set the primary Layer Colours by guess work! */
	GRSetColor(LAYER_DEVICE);
	GRMoveTo(PartX + TransMat[0][0] * x1 + TransMat[0][1] * y1,
		 PartY + TransMat[1][0] * x1 + TransMat[1][1] * y1);
	GRLineTo(PartX + TransMat[0][0] * x1 + TransMat[0][1] * y2,
		 PartY + TransMat[1][0] * x1 + TransMat[1][1] * y2);
	GRLineTo(PartX + TransMat[0][0] * x2 + TransMat[0][1] * y2,
		 PartY + TransMat[1][0] * x2 + TransMat[1][1] * y2);
	GRLineTo(PartX + TransMat[0][0] * x2 + TransMat[0][1] * y1,
		 PartY + TransMat[1][0] * x2 + TransMat[1][1] * y1);
	GRLineTo(PartX + TransMat[0][0] * x1 + TransMat[0][1] * y1,
		 PartY + TransMat[1][0] * x1 + TransMat[1][1] * y1);
	for (i = 0; i < Entry -> NumOfPins / 2; i++) {
	    y = y2 - PinWidth / 2 - i * PinWidth;
	    MapX1 = PartX + TransMat[0][0] * x1 + TransMat[0][1] * y;
	    MapY1 = PartY + TransMat[1][0] * x1 + TransMat[1][1] * y;
	    MapX2 = PartX + TransMat[0][0] * (x1 - PIN_LENGTH) + TransMat[0][1] * y;
	    MapY2 = PartY + TransMat[1][0] * (x1 - PIN_LENGTH) + TransMat[1][1] * y;
	    GRMoveTo(MapX1, MapY1);
	    GRLineTo(MapX2, MapY2);
		    if(Mode==0)
			GRSetColor(EE_ERASE_COLOR);
		    else
			GRSetColor(ReturnLayerColor(LAYER_PIN));
		    if(ReturnLayerMode(LAYER_PIN))
		    	GRCircle(x2,y2,3);
		    
		    if((!(ReturnLayerMode(DEntry -> Layer) & 0x03)) & (Mode==1)) 			break;
		    else if(Mode==0)
			GRSetColor(EE_ERASE_COLOR);
		    else
			GRSetColor(ReturnLayerColor(DEntry -> Layer));
	    if (IsMulti) {
		GRSetColor(LAYER_PINNUM);
		PutLineTextInfo(MapX1, MapY1, MapX2, MapY2,
		    LookUpPinText(Entry -> Pins, *NextPinMulti),
		    *NextPinMulti,
		    Entry -> TextInside,
		    Entry -> DrawNums,Mode);
		NextPinMulti++;
	    }
	    else {
		GRSetColor(LAYER_PINNUM);
		PutLineTextInfo(MapX1, MapY1, MapX2, MapY2,
		    NextPinText,
		    NextPinNum,
		    Entry -> TextInside,
		    Entry -> DrawNums,Mode);
		NextPinText = strtok(NULL, PIN_SEPERATOR);
		NextPinNum++;
	    }
	}
	for (i = Entry -> NumOfPins / 2 + 1; i <= Entry -> NumOfPins; i++) {
	    y = y1 + PinWidth / 2 + (i - Entry -> NumOfPins / 2 - 1) *
							    PinWidth;
	    MapX1 = PartX + TransMat[0][0] * x2 + TransMat[0][1] * y;
	    MapY1 = PartY + TransMat[1][0] * x2 + TransMat[1][1] * y;
	    MapX2 = PartX + TransMat[0][0] * (x2 + PIN_LENGTH) + TransMat[0][1] * y;
	    MapY2 = PartY + TransMat[1][0] * (x2 + PIN_LENGTH) + TransMat[1][1] * y;
/* Set the primary Layer Colours by guess work! */
	GRSetColor(LAYER_DEVICE);
	    GRMoveTo(MapX1, MapY1);
	    GRLineTo(MapX2, MapY2);
		    if(Mode==0)
			GRSetColor(EE_ERASE_COLOR);
		    else
			GRSetColor(ReturnLayerColor(LAYER_PIN));
		    if(ReturnLayerMode(LAYER_PIN))
		    	GRCircle(x2,y2,3);
		    
		    if((!(ReturnLayerMode(DEntry -> Layer) & 0x03)) & (Mode==1)) 			break;
		    else if(Mode==0)
			GRSetColor(EE_ERASE_COLOR);
		    else
			GRSetColor(ReturnLayerColor(DEntry -> Layer));
	    if (IsMulti) {
		GRSetColor(LAYER_PINNUM);
		PutLineTextInfo(MapX1, MapY1, MapX2, MapY2,
		    LookUpPinText(Entry -> Pins, *NextPinMulti),
		    *NextPinMulti,
		    Entry -> TextInside,
		    Entry -> DrawNums,Mode);
		NextPinMulti++;
	    }
	    else {
		GRSetColor(LAYER_PINNAM);
		PutLineTextInfo(MapX1, MapY1, MapX2, MapY2,
		    NextPinText,
		    NextPinNum,
		    Entry -> TextInside,
		    Entry -> DrawNums,Mode);
		NextPinText = strtok(NULL, PIN_SEPERATOR);
		NextPinNum++;
	    }
	}
    }
}

/*****************************************************************************
* Routine to find the closest connection point of the library item to the    *
* given point and set ClosestX/Y to it.					     *
* As the only connections are defined via LINE definition only those are     *
* tested. More than that - only the second point entry of LINE is tested as  *
* the first one is the connection to the object itself.			     *
*****************************************************************************/
void SnapLibItemPoint(int OrigX, int OrigY, int *ClosestX, int *ClosestY,
						DrawLibItemStruct *DrawLibItem)
{
    int i, TempX, TempY, TempY1, TransMat[2][2], PartX, PartY, *Points,
	x1, y1, x2, y2, PinWidth;
    unsigned int Dist;
    char Line[LINE_LEN_SHORT];
    LibraryEntryStruct *Entry;
    LibraryDrawEntryStruct *DEntry;

    GEN_COPY(TransMat, DrawLibItem -> Transform, sizeof(int) * 4);
    PartX = DrawLibItem -> PosX;
    PartY = DrawLibItem -> PosY;
    Dist = ((unsigned int) ABS(*ClosestX - OrigX)) +
	   ((unsigned int) ABS(*ClosestY - OrigY));

    Cursor.CursorType = INTR_CURSOR_ARROW;

    if ((Entry = FindLibPart(DrawLibItem -> ChipName)) == NULL) {
	sprintf(Line, "Failed to find part \"%s\" in library",
						DrawLibItem -> PartName);
	IntrQueryContinue(Line, EEPopUpFrameColor,
			  EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
			  EEWindowsFrameWidth, &Cursor,
                          INTR_WNDW_PLACE_CENTER);
	return;
    }

    if (Entry -> Drawings != NULL) {
	DEntry = Entry -> Drawings;
	while (DEntry != NULL) {
	    switch (DEntry -> DrawType) {
		case LINE_DRAW_TYPE:
		    TempX = PartX + TransMat[0][0] * DEntry -> U.Line.x1
					+ TransMat[0][1] * DEntry -> U.Line.y1;
		    TempY = PartY + TransMat[1][0] * DEntry -> U.Line.x1
					+ TransMat[1][1] * DEntry -> U.Line.y1;
		    if (((unsigned int) ABS(TempX - OrigX)) +
			((unsigned int) ABS(TempY - OrigY)) < Dist) {
			*ClosestX = TempX;
			*ClosestY = TempY;
			Dist = ((unsigned int) ABS(TempX - OrigX)) +
			       ((unsigned int) ABS(TempY - OrigY));
		    }
		    TempX = PartX + TransMat[0][0] * DEntry -> U.Line.x2
					+ TransMat[0][1] * DEntry -> U.Line.y2;
		    TempY = PartY + TransMat[1][0] * DEntry -> U.Line.x2
					+ TransMat[1][1] * DEntry -> U.Line.y2;
		    if (((unsigned int) ABS(TempX - OrigX)) +
			((unsigned int) ABS(TempY - OrigY)) < Dist) {
			*ClosestX = TempX;
			*ClosestY = TempY;
			Dist = ((unsigned int) ABS(TempX - OrigX)) +
			       ((unsigned int) ABS(TempY - OrigY));
		    }
		    break;
		case SQUARE_DRAW_TYPE:
		    TempX = PartX + TransMat[0][0] * DEntry -> U.Sqr.x1
					+ TransMat[0][1] * DEntry -> U.Sqr.y1;
		    TempY = PartY + TransMat[1][0] * DEntry -> U.Sqr.x1
					+ TransMat[1][1] * DEntry -> U.Sqr.y1;
		    if (((unsigned int) ABS(TempX - OrigX)) +
			((unsigned int) ABS(TempY - OrigY)) < Dist) {
			*ClosestX = TempX;
			*ClosestY = TempY;
			Dist = ((unsigned int) ABS(TempX - OrigX)) +
			       ((unsigned int) ABS(TempY - OrigY));
		    }

		    TempX = PartX + TransMat[0][0] * DEntry -> U.Sqr.x2
					+ TransMat[0][1] * DEntry -> U.Sqr.y2;
		    TempY = PartY + TransMat[1][0] * DEntry -> U.Sqr.x2
					+ TransMat[1][1] * DEntry -> U.Sqr.y2;
		    if (((unsigned int) ABS(TempX - OrigX)) +
			((unsigned int) ABS(TempY - OrigY)) < Dist) {
			*ClosestX = TempX;
			*ClosestY = TempY;
			Dist = ((unsigned int) ABS(TempX - OrigX)) +
			       ((unsigned int) ABS(TempY - OrigY));
		    }

		    TempX = PartX + TransMat[0][0] * DEntry -> U.Sqr.x2
					+ TransMat[0][1] * DEntry -> U.Sqr.y1;
		    TempY = PartY + TransMat[1][0] * DEntry -> U.Sqr.x2
					+ TransMat[1][1] * DEntry -> U.Sqr.y1;
		    if (((unsigned int) ABS(TempX - OrigX)) +
			((unsigned int) ABS(TempY - OrigY)) < Dist) {
			*ClosestX = TempX;
			*ClosestY = TempY;
			Dist = ((unsigned int) ABS(TempX - OrigX)) +
			       ((unsigned int) ABS(TempY - OrigY));
		    }

		    TempX = PartX + TransMat[0][0] * DEntry -> U.Sqr.x1
					+ TransMat[0][1] * DEntry -> U.Sqr.y2;
		    TempY = PartY + TransMat[1][0] * DEntry -> U.Sqr.x1
					+ TransMat[1][1] * DEntry -> U.Sqr.y2;
		    if (((unsigned int) ABS(TempX - OrigX)) +
			((unsigned int) ABS(TempY - OrigY)) < Dist) {
			*ClosestX = TempX;
			*ClosestY = TempY;
			Dist = ((unsigned int) ABS(TempX - OrigX)) +
			       ((unsigned int) ABS(TempY - OrigY));
		    }
		    break;
		case POLYLINE_DRAW_TYPE:
		    Points = DEntry -> U.Poly.PolyList;
		    for (i = 0; i < DEntry -> U.Poly.n; i++) {
			TempX = PartX + TransMat[0][0] * Points[i * 2]
				      + TransMat[0][1] * Points[i * 2 + 1];
			TempY = PartY + TransMat[1][0] * Points[i * 2]
				      + TransMat[1][1] * Points[i * 2 + 1];

			if (((unsigned int) ABS(TempX - OrigX)) +
			    ((unsigned int) ABS(TempY - OrigY)) < Dist) {
			    *ClosestX = TempX;
			    *ClosestY = TempY;
			    Dist = ((unsigned int) ABS(TempX - OrigX)) +
				   ((unsigned int) ABS(TempY - OrigY));
		    }
		    }
		    break;
		case ARC_DRAW_TYPE:
		case CIRCLE_DRAW_TYPE:
		case TEXT_DRAW_TYPE:
		    break;
	    }
	    DEntry = DEntry -> Pnext;
	}
    }
    else {				      /* Simple a box with all pins: */
	y1 = Entry -> TextInside ? PIN_WIDTH * Entry -> NumOfPins / 4 :
				   PIN_WIDTH * Entry -> NumOfPins / 2;
	x1 = Entry -> TextInside ? (int) (y1 * CHIP_BOX_ASPECT_TI) :
				   (int) (y1 * CHIP_BOX_ASPECT_TO);
	/* But make sure we can still print somethings inside... */
	if (x1 < DRAW_TEXT_WIDTH * 12) x1 = DRAW_TEXT_WIDTH * 12;
	x2 = x1 / 2;
	y2 = y1 / 2;
	x1 = -x2;
	y1 = -y2;
	PinWidth = Entry -> TextInside ? PIN_WIDTH / 2 : PIN_WIDTH;

	for (i = 0; i < Entry -> NumOfPins / 2; i++) {
	    TempY1 = y2 - PinWidth / 2 - i * PinWidth;
	    TempX = PartX + TransMat[0][0] * (x1 - PIN_LENGTH) +
			    TransMat[0][1] * TempY1;
	    TempY = PartY + TransMat[1][0] * (x1 - PIN_LENGTH) +
			    TransMat[1][1] * TempY1;
	    if (((unsigned int) ABS(TempX - OrigX)) +
		((unsigned int) ABS(TempY - OrigY)) < Dist) {
		*ClosestX = TempX;
		*ClosestY = TempY;
		Dist = ((unsigned int) ABS(TempX - OrigX)) +
		       ((unsigned int) ABS(TempY - OrigY));
	    }
	}
	for (i = Entry -> NumOfPins / 2 + 1; i <= Entry -> NumOfPins; i++) {
	    TempY1 = y1 + PinWidth / 2 + (i - Entry -> NumOfPins / 2 - 1) *
								PinWidth;
	    TempX = PartX + TransMat[0][0] * (x2 + PIN_LENGTH) +
			    TransMat[0][1] * TempY1;
	    TempY = PartY + TransMat[1][0] * (x2 + PIN_LENGTH) +
			    TransMat[1][1] * TempY1;
	    if (((unsigned int) ABS(TempX - OrigX)) +
		((unsigned int) ABS(TempY - OrigY)) < Dist) {
		*ClosestX = TempX;
		*ClosestY = TempY;
		Dist = ((unsigned int) ABS(TempX - OrigX)) +
		       ((unsigned int) ABS(TempY - OrigY));
	    }
	}
    }
}

/*****************************************************************************
* Routine to find all pins that have connection to the line from x1/y1 to    *
* x2/y2 in Library item provided. Only terminals (LINE_DRAW_TYPE) are tested.*
*****************************************************************************/
NetListStruct *FindLibItemNetList(int lx1, int ly1, int lx2, int ly2,
				  BooleanType l1Bus,
				  DrawGenericStruct *Phead,
				  DrawLibItemStruct *DrawLibItem)
{
    int i, j, IsMulti, Multi, *NextPinMulti, TransMat[2][2], PartX, PartY,
	NextPinNum, PinWidth, y, x1, y1, x2, y2, MapX1, MapY1, MapX2, MapY2;
    char *p, *NextPinText, Line[LINE_LEN];
    LibraryEntryStruct *Entry;
    LibraryDrawEntryStruct *DEntry;
    NetListStruct
	*NetList = NULL;

    GEN_COPY(TransMat, DrawLibItem -> Transform, sizeof(int) * 4);
    PartX = DrawLibItem -> PosX;
    PartY = DrawLibItem -> PosY;
    Multi = DrawLibItem -> Multi;

    if ((Entry = FindLibPart(DrawLibItem -> ChipName)) == NULL) {
	sprintf(Line, "Failed to find part \"%s\" in library",
						DrawLibItem -> PartName);
	IntrQueryContinue(Line, EEPopUpFrameColor,
			  EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
			  EEWindowsFrameWidth, &Cursor,
			  INTR_WNDW_PLACE_CENTER);
	return NULL;
    }

    IsMulti = Entry -> NumOfUnits > 0;
    if (IsMulti) {
	/* Make NextMulti point on next pin number in multi array: */
	NextPinMulti = &Entry -> Multi[Entry -> PinsPerUnit * --Multi];

	NextPinText = NULL;
    }
    else {
	NextPinNum = 1;
	NextPinMulti = NULL;

	/* Make a copy of all pin text info so we can use strtok routine on: */
	strncpy(Line, Entry -> Pins, LINE_LEN - 1);
	NextPinText = strtok(Line, PIN_SEPERATOR);
    }

    if (Entry -> Drawings != NULL) {
	DEntry = Entry -> Drawings;
	while (DEntry != NULL) {
	    switch (DEntry -> DrawType) {
		case LINE_DRAW_TYPE:
		    x1 = PartX + TransMat[0][0] * DEntry -> U.Line.x1
			       + TransMat[0][1] * DEntry -> U.Line.y1;
		    y1 = PartY + TransMat[1][0] * DEntry -> U.Line.x1
			       + TransMat[1][1] * DEntry -> U.Line.y1;
		    x2 = PartX + TransMat[0][0] * DEntry -> U.Line.x2
			       + TransMat[0][1] * DEntry -> U.Line.y2;
		    y2 = PartY + TransMat[1][0] * DEntry -> U.Line.x2
			       + TransMat[1][1] * DEntry -> U.Line.y2;
		    if (IsMulti) {
			p = LookUpPinText(Entry -> Pins, j = *NextPinMulti);
			NextPinMulti++;
		    }
		    else {
			p = NextPinText;
			NextPinText = strtok(NULL, PIN_SEPERATOR);
			j = NextPinNum++;
		    }

		    if (LinesIntersect(lx1, ly1, lx2, ly2, x1, y1, x2, y2,
						       l1Bus, FALSE, Phead))
			PushNetListItem(&NetList, x1, y1, x2, y2,
					DrawLibItem -> PartName,
					DrawLibItem -> ChipName, p, j);
		    break;
	    }
	    DEntry = DEntry -> Pnext;
	}
    }
    else {				      /* Simple a box with all pins: */
	PinWidth = Entry -> TextInside ? PIN_WIDTH / 2 : PIN_WIDTH;
	y1 = Entry -> TextInside ? PIN_WIDTH * Entry -> NumOfPins / 4 :
				   PIN_WIDTH * Entry -> NumOfPins / 2;
	x1 = Entry -> TextInside ? (int) (y1 * CHIP_BOX_ASPECT_TI) :
				   (int) (y1 * CHIP_BOX_ASPECT_TO);
	/* But make sure we can still print somethings inside... */
	if (x1 < DRAW_TEXT_WIDTH * 12) x1 = DRAW_TEXT_WIDTH * 12;
	x2 = x1 / 2;
	y2 = y1 / 2;
	x1 = -x2;
	y1 = -y2;

	for (i = 0; i < Entry -> NumOfPins / 2; i++) {
	    y = y2 - PinWidth / 2 - i * PinWidth;
	    MapX1 = PartX + TransMat[0][0] * x1 + TransMat[0][1] * y;
	    MapY1 = PartY + TransMat[1][0] * x1 + TransMat[1][1] * y;
	    MapX2 = PartX + TransMat[0][0] * (x1 - PIN_LENGTH) + TransMat[0][1] * y;
	    MapY2 = PartY + TransMat[1][0] * (x1 - PIN_LENGTH) + TransMat[1][1] * y;
	    if (IsMulti) {
		p = LookUpPinText(Entry -> Pins, j = *NextPinMulti);
		NextPinMulti++;
	    }
	    else {
		p = NextPinText;
		NextPinText = strtok(NULL, PIN_SEPERATOR);
		j = NextPinNum++;
	    }

	    if (LinesIntersect(lx1, ly1, lx2, ly2,
			       MapX1, MapY1, MapX2, MapY2,
			       l1Bus, FALSE, Phead))
		PushNetListItem(&NetList, MapX1, MapY1, MapX2, MapY2,
				DrawLibItem -> PartName,
				DrawLibItem -> ChipName, p, j);
	}
	for (i = Entry -> NumOfPins / 2 + 1; i <= Entry -> NumOfPins; i++) {
	    y = y1 + PinWidth / 2 + (i - Entry -> NumOfPins / 2 - 1) *
							    PinWidth;
	    MapX1 = PartX + TransMat[0][0] * x2 + TransMat[0][1] * y;
	    MapY1 = PartY + TransMat[1][0] * x2 + TransMat[1][1] * y;
	    MapX2 = PartX + TransMat[0][0] * (x2 + PIN_LENGTH) + TransMat[0][1] * y;
	    MapY2 = PartY + TransMat[1][0] * (x2 + PIN_LENGTH) + TransMat[1][1] * y;
	    if (IsMulti) {
		p = LookUpPinText(Entry -> Pins, *NextPinMulti);
		NextPinMulti++;
	    }
	    else {
		p = NextPinText;
		NextPinText = strtok(NULL, PIN_SEPERATOR);
		NextPinNum++;
	    }
	    if (LinesIntersect(lx1, ly1, lx2, ly2,
			       MapX1, MapY1, MapX2, MapY2,
			       l1Bus, FALSE, Phead))
		PushNetListItem(&NetList, MapX1, MapY1, MapX2, MapY2,
				DrawLibItem -> PartName,
				DrawLibItem -> ChipName, p, j);
	}
    }

    return NetList;
}

/*****************************************************************************
* Routine to push one net list item on the NetList list.		     *
* In addition the library item L line is drawn in current color/mode.        *
*****************************************************************************/
static void PushNetListItem(NetListStruct **NetList,
			    int MapX1, int MapY1, int MapX2, int MapY2,
			    char *PartName, char *ChipName, char *PinName,
			    int PinNum)
{
    struct NetListStruct *NetListItem = (NetListStruct *)
					      MyMalloc(sizeof(NetListStruct));

    if (ChipName == NULL) ChipName = "";
    if (PartName == NULL) PartName = "";
    if (PinName == NULL) PinName = "";

    if (ChipName[0] == '~') ChipName = &ChipName[1];
    if (PartName[0] == '~') PartName = &PartName[1];
    if (PinName[0] == '~') PinName = &PinName[1];

    sprintf(NetListItem -> Pin, "%s %s %s (Pin %d)",
	    ChipName, PartName, PinName, PinNum);

    NetListItem -> Pnext = *NetList;
    *NetList = NetListItem;

    GRMoveTo(MapX1, MapY1);
    GRLineTo(MapX2, MapY2);
}

/*****************************************************************************
* Routine to test if the given library item has non empty intersection with  *
* the given box defined by x1/y1 and x2/y2 (x1 < x2, y1 < y2) and return     *
* TRUE if so. Used to pick objects in a given box.			     *
*****************************************************************************/
BooleanType LibItemInBox(int x1, int y1, int x2, int y2,
						DrawLibItemStruct *DrawLibItem)
{
    int i, TempX, TempY, TempY1, TransMat[2][2], PartX, PartY, *Points,
	xt1, yt1, xt2, yt2, PinWidth;
    char Line[LINE_LEN_SHORT];
    LibraryEntryStruct *Entry;
    LibraryDrawEntryStruct *DEntry;

    GEN_COPY(TransMat, DrawLibItem -> Transform, sizeof(int) * 4);
    PartX = DrawLibItem -> PosX;
    PartY = DrawLibItem -> PosY;

    Cursor.CursorType = INTR_CURSOR_ARROW;

    if ((Entry = FindLibPart(DrawLibItem -> ChipName)) == NULL) {
	sprintf(Line, "Failed to find part \"%s\" in library",
						DrawLibItem -> PartName);
	IntrQueryContinue(Line, EEPopUpFrameColor,
        		  EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
                          EEWindowsFrameWidth, &Cursor,
                          INTR_WNDW_PLACE_CENTER);
	return FALSE;
    }

    if (Entry -> Drawings != NULL) {
	DEntry = Entry -> Drawings;
	while (DEntry != NULL) {
	    switch (DEntry -> DrawType) {
		case LINE_DRAW_TYPE:
		    TempX = PartX + TransMat[0][0] * DEntry -> U.Line.x1
					+ TransMat[0][1] * DEntry -> U.Line.y1;
		    TempY = PartY + TransMat[1][0] * DEntry -> U.Line.x1
					+ TransMat[1][1] * DEntry -> U.Line.y1;
		    if (TempX >= x1 && TempX <= x2 &&
			TempY >= y1 && TempY <= y2) return TRUE;

		    TempX = PartX + TransMat[0][0] * DEntry -> U.Line.x2
					+ TransMat[0][1] * DEntry -> U.Line.y2;
		    TempY = PartY + TransMat[1][0] * DEntry -> U.Line.x2
					+ TransMat[1][1] * DEntry -> U.Line.y2;
		    if (TempX >= x1 && TempX <= x2 &&
			TempY >= y1 && TempY <= y2) return TRUE;
		    break;
		case SQUARE_DRAW_TYPE:
		    TempX = PartX + TransMat[0][0] * DEntry -> U.Sqr.x1
					+ TransMat[0][1] * DEntry -> U.Sqr.y1;
		    TempY = PartY + TransMat[1][0] * DEntry -> U.Sqr.x1
					+ TransMat[1][1] * DEntry -> U.Sqr.y1;
		    if (TempX >= x1 && TempX <= x2 &&
			TempY >= y1 && TempY <= y2) return TRUE;

		    TempX = PartX + TransMat[0][0] * DEntry -> U.Sqr.x2
					+ TransMat[0][1] * DEntry -> U.Sqr.y2;
		    TempY = PartY + TransMat[1][0] * DEntry -> U.Sqr.x2
					+ TransMat[1][1] * DEntry -> U.Sqr.y2;
		    if (TempX >= x1 && TempX <= x2 &&
			TempY >= y1 && TempY <= y2) return TRUE;

		    TempX = PartX + TransMat[0][0] * DEntry -> U.Sqr.x2
					+ TransMat[0][1] * DEntry -> U.Sqr.y1;
		    TempY = PartY + TransMat[1][0] * DEntry -> U.Sqr.x2
					+ TransMat[1][1] * DEntry -> U.Sqr.y1;
		    if (TempX >= x1 && TempX <= x2 &&
			TempY >= y1 && TempY <= y2) return TRUE;

		    TempX = PartX + TransMat[0][0] * DEntry -> U.Sqr.x1
					+ TransMat[0][1] * DEntry -> U.Sqr.y2;
		    TempY = PartY + TransMat[1][0] * DEntry -> U.Sqr.x1
					+ TransMat[1][1] * DEntry -> U.Sqr.y2;
		    if (TempX >= x1 && TempX <= x2 &&
			TempY >= y1 && TempY <= y2) return TRUE;
		    break;
		case POLYLINE_DRAW_TYPE:
		    Points = DEntry -> U.Poly.PolyList;
		    for (i = 0; i < DEntry -> U.Poly.n; i++) {
			TempX = PartX + TransMat[0][0] * Points[i * 2]
				      + TransMat[0][1] * Points[i * 2 + 1];
			TempY = PartY + TransMat[1][0] * Points[i * 2]
				      + TransMat[1][1] * Points[i * 2 + 1];
			if (TempX >= x1 && TempX <= x2 &&
			    TempY >= y1 && TempY <= y2) return TRUE;

		    }
		    break;
		case ARC_DRAW_TYPE:
		case CIRCLE_DRAW_TYPE:
		case TEXT_DRAW_TYPE:
		    break;
	    }
	    DEntry = DEntry -> Pnext;
	}
    }
    else {				      /* Simple a box with all pins: */
	yt1 = Entry -> TextInside ? PIN_WIDTH * Entry -> NumOfPins / 4 :
				    PIN_WIDTH * Entry -> NumOfPins / 2;
	xt1 = Entry -> TextInside ? (int) (yt1 * CHIP_BOX_ASPECT_TI) :
				    (int) (yt1 * CHIP_BOX_ASPECT_TO);
        /* But make sure we can still print somethings inside... */
	if (xt1 < DRAW_TEXT_WIDTH * 12) xt1 = DRAW_TEXT_WIDTH * 12;
	xt2 = xt1 / 2;
	yt2 = yt1 / 2;
	xt1 = -xt2;
	yt1 = -yt2;
	PinWidth = Entry -> TextInside ? PIN_WIDTH / 2 : PIN_WIDTH;

	for (i = 0; i < Entry -> NumOfPins / 2; i++) {
	    TempY1 = yt2 - PinWidth / 2 - i * PinWidth;
	    TempX = PartX + TransMat[0][0] * (xt1 - PIN_LENGTH) +
			    TransMat[0][1] * TempY1;
	    TempY = PartY + TransMat[1][0] * (xt1 - PIN_LENGTH) +
			    TransMat[1][1] * TempY1;
	    if (TempX >= x1 && TempX <= x2 &&
		TempY >= y1 && TempY <= y2) return TRUE;
	}
	for (i = Entry -> NumOfPins / 2 + 1; i <= Entry -> NumOfPins; i++) {
	    TempY1 = yt1 + PinWidth / 2 + (i - Entry -> NumOfPins / 2 - 1) *
								PinWidth;
	    TempX = PartX + TransMat[0][0] * (xt2 + PIN_LENGTH) +
			    TransMat[0][1] * TempY1;
	    TempY = PartY + TransMat[1][0] * (xt2 + PIN_LENGTH) +
			    TransMat[1][1] * TempY1;
	    if (TempX >= x1 && TempX <= x2 &&
		TempY >= y1 && TempY <= y2) return TRUE;
	}
    }

    return FALSE;
}

/*****************************************************************************
* Given the Pins string and PinNum returns NULL terminated string of that    *
* pin allocated statically.						     *
*****************************************************************************/
static char *LookUpPinText(char *Pins, int PinNum)
{
    static char Pin[MAX_PIN_INFO];
    int i,
        Count = 1;

    while (*Pins && Count != PinNum) {
	if (*Pins++ == PIN_SEPERATOR[0]) Count++;
    }

    if (*Pins) {
	i = 0;
	while (i < MAX_PIN_INFO - 1 && *Pins != PIN_SEPERATOR[0] && *Pins != 0)
	    Pin[i++] = *Pins++;
	Pin[i] = 0;
	return i > 0 ? Pin : NULL;
    }
    else {
	return NULL;
    }
}

/*****************************************************************************
* Routine to rotate the given angular direction by the given Transformation. *
* Input (and output) angles must be as follows:				     *
* Angle1 in [0..360], Angle2 > Angle1 in [0..720]. Arc is assumed to be less *
* than 180 degrees.							     *
* Algorithm:								     *
* Map the angles to a point on the unit circle which is mapped using the     *
* transform (only mirror and rotate so it remains on the unit circle) to     *
* a new point which is used to detect new angle.			     *
*****************************************************************************/
static void MapAngles(int *Angle1, int *Angle2, int TransMat[2][2])
{
    int Angle;
    RealType x, y, t;

    x = cos(*Angle1 * M_PI / 180.0);
    y = sin(*Angle1 * M_PI / 180.0);
    t = x * TransMat[0][0] + y * TransMat[0][1];
    y = x * TransMat[1][0] + y * TransMat[1][1];
    x = t;
    *Angle1 = (int) (atan2(y, x) * 180.0 / M_PI + 0.5);

    x = cos(*Angle2 * M_PI / 180.0);
    y = sin(*Angle2 * M_PI / 180.0);
    t = x * TransMat[0][0] + y * TransMat[0][1];
    y = x * TransMat[1][0] + y * TransMat[1][1];
    x = t;
    *Angle2 = (int) (atan2(y, x) * 180.0 / M_PI + 0.5);

    NORMALIZE_ANGLE(*Angle1);
    NORMALIZE_ANGLE(*Angle2);
    if (*Angle2 < *Angle1) *Angle2 += 360;

    if (*Angle2 - *Angle1 > 180) {	     /* Need to swap the two angles. */
	Angle = (*Angle1);
	*Angle1 = (*Angle2);
	*Angle2 = Angle;

	NORMALIZE_ANGLE(*Angle1);
	NORMALIZE_ANGLE(*Angle2);
	if (*Angle2 < *Angle1) *Angle2 += 360;
    }

    *Angle1 -= 1;    /* As the angles loaded are decreased by 1 when loaded. */
    *Angle2 += 1;
}

/*****************************************************************************
* Routine to view one selected library content.				     *
*****************************************************************************/
static void ViewOneLibrary(LibraryStruct *Lib)
{
    int i, x, y, TransMat[2][2],
	NumOfParts = Lib -> NumOfParts;
    char **PartNames;
    LibraryEntryStruct *LibEntry, *Entry,
	*LastEntry = NULL;

    Cursor.CursorType = INTR_CURSOR_ARROW;

    if (NumOfParts == 0) {
	IntrQueryContinue("Library is empty!", EEPopUpFrameColor,
        		  EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
                          EEWindowsFrameWidth, &Cursor,
                          INTR_WNDW_PLACE_CENTER);
	return;
    }
    PartNames = (char **) MyMalloc(sizeof(char *) * NumOfParts);

    PQCompFunc((PQCompFuncType) LibraryEntryCompare);
    LibEntry = (LibraryEntryStruct *) PQFirst(&Lib -> Entries, FALSE);
    PartNames[0] = LibEntry -> Name;
    for (i = 1; i < NumOfParts; i++) {
	if ((LibEntry = (LibraryEntryStruct *)
	      PQNext(Lib -> Entries, LibEntry, NULL)) == NULL) {
	    /* Number of parts does not match what we really have. This is   */
	    /* wierd but we will try to do what we can:			     */
	    NumOfParts = i - 1;
	    break;
	}
	PartNames[i] = LibEntry -> Name;
    }

    x = GRInvMapX(GRScreenMaxX * 3 / 4);     /* Where to put the drawn part: */
    y = GRInvMapY(GRScreenMaxY / 2);
    TransMat[0][0] = 1.0;
    TransMat[1][1] = -1.0;
    TransMat[1][0] = TransMat[0][1] = 0.0;

    do {
	i = IntrQueryList("ViewLib", (char **) PartNames, 0, NumOfParts,
			  EEListNumDisplayed, EEPopUpFrameColor,
                          EEPopUpBackColor, EEPopUpForeColor,
                          EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
                          INTR_WNDW_PLACE_LEFT);

	if (LastEntry) {				  /* Erase old part. */
	    DrawLibPartAux(LastEntry, x, y, TransMat, 1, GR_COPY_PUT,
                          IntrAllocColor(EERootWndwBackColor,
		                        INTR_INTENSITY_HIGH ));
	    LastEntry = NULL;
	}

	if (i >= 0) {					   /* Draw new part. */
	    Entry = FindLibPart(PartNames[i]);
	    DrawLibPartAux(Entry, x, y, TransMat,
				               1, GR_COPY_PUT, 1);
	    LastEntry = Entry;
	}
    }
    while (i >= 0);

    MyFree((VoidPtr) PartNames);
}

/*****************************************************************************
* Routine to handle lib part creation. Return NULL if fails.		     *
*****************************************************************************/
DrawGenericStruct *LibCreateNewPart(void)
{
    static char Name[LINE_LEN_SHORT] = { 0 };
    int x, y, TransMat[2][2], TempMat[2][2], TempR, Multi, PopPosition;
    BooleanType Transform,
	Quit = FALSE;
    char Line[LINE_LEN], Buffer[LINE_LEN_SHORT];
    char L2[LINE_LEN];
    LibraryEntryStruct *Entry;
    DrawLibItemStruct *DrawLibItem;

    IntrQueryLine("Library part name:", Name, LINE_LEN_SHORT - 1,
    		  EEPopUpFrameColor, EEPopUpBackColor, EEPopUpForeColor,
                  EEWindowsFrameWidth, INTR_WNDW_PLACE_CENTER);

    if (strlen(Name) == 0) return NULL;
    strupr(Name);

    Cursor.CursorType = INTR_CURSOR_ARROW;

    if ((Entry = FindLibPart(Name)) == NULL) {
	sprintf(Line, "Failed to find part \"%s\" in library", Name);
	IntrQueryContinue(Line, EEPopUpFrameColor,
        		  EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
                          EEWindowsFrameWidth, &Cursor, INTR_WNDW_PLACE_CENTER);
	return NULL;
    }

    if (Entry -> NumOfUnits > 1) {
	do {
	    sprintf(Line, "This chip has %d multiple units. Which one (1-%d):",
				Entry -> NumOfUnits, Entry -> NumOfUnits);
	    strcpy(Buffer, "1");
	    IntrQueryLine(Line, Buffer, LINE_LEN_SHORT - 1,
    		          EEPopUpFrameColor, EEPopUpBackColor,
                          EEPopUpForeColor, EEWindowsFrameWidth,
                          INTR_WNDW_PLACE_CENTER);
	}
	while (sscanf(Buffer, "%d", &Multi) != 1 ||
	       Multi <= 0 ||
	       Multi > Entry -> NumOfUnits);
    }
    else
	Multi = 1;

    x = GRScreenMaxX * 3 / 4;		     /* Where to put the drawn part: */
    y = GRScreenMaxY / 2;

    /* Prepare the transformation information: */
    TransMat[0][0] = 1.0;
    TransMat[1][1] = -1.0;
    TransMat[1][0] = TransMat[0][1] = 0.0;

    if (TransPopUpMenu == NULL) TransPopUpMenu =
        IntrPopUpMenuCreate("Transform", (char **) TransformStrs, 0,
        		    TRANS_MENU_SIZE, EEPopUpFrameColor,
                            EEPopUpBackColor, EEPopUpForeColor,
                            EEPopUpXorColor, EEWindowsFrameWidth, &Cursor);

    do {

	DrawLibPartAux(Entry, GRInvMapX(x), GRInvMapY(y), TransMat,
		       Multi, GR_COPY_PUT, 1);

	if (!IntrPopUpMenu(TransPopUpMenu, INTR_WNDW_PLACE_LEFT)) {
            /* If abort key. */

	    DrawLibPartAux(Entry, GRInvMapX(x), GRInvMapY(y), TransMat,
		           Multi, GR_COPY_PUT, 0);

	    return NULL;
	}

	DrawLibPartAux(Entry, GRInvMapX(x), GRInvMapY(y), TransMat,
		       Multi, GR_COPY_PUT, 0);

	Transform = TRUE;
	if (!Quit) switch (TransPopUpMenu -> SelectedIndex) {
	    case 0:
		Quit = TRUE;
		break;
	    case 2:
		TempMat[0][0] = TempMat[1][1] = 0.0;
		TempMat[0][1] = 1.0;
		TempMat[1][0] = -1.0;
		break;
	    case 3:
		TempMat[0][0] = TempMat[1][1] = 0.0;
		TempMat[0][1] = -1.0;
		TempMat[1][0] = 1.0;
		break;
	    case 4:
		TempMat[0][0] = -1.0;
		TempMat[1][1] = 1.0;
		TempMat[0][1] = TempMat[1][0] = 0.0;
		break;
	    case 5:
		TempMat[0][0] = 1.0;
		TempMat[1][1] = -1.0;
		TempMat[0][1] = TempMat[1][0] = 0.0;
		break;
	    default:
		Transform = FALSE;
		break;
	}
	if (!Quit && Transform) {
	    TempR = TransMat[0][0] * TempMat[0][0] +
						TransMat[0][1] * TempMat[1][0];
	    TransMat[0][1] = TransMat[0][0] * TempMat[0][1] +
						TransMat[0][1] * TempMat[1][1];
	    TransMat[0][0] = TempR;
	    TempR = TransMat[1][0] * TempMat[0][0] +
						TransMat[1][1] * TempMat[1][0];
	    TransMat[1][1] = TransMat[1][0] * TempMat[0][1] +
						TransMat[1][1] * TempMat[1][1];
	    TransMat[1][0] = TempR;
	}
    }
    while (!Quit);

    /* Allocate the structure to be returned, and fill it with information   */
    /* we know so far.							     */
    DrawLibItem = (DrawLibItemStruct *) MyMalloc(sizeof(DrawLibItemStruct));
    DrawLibItem -> Pnext = NULL;
    DrawLibItem -> StructType = DRAW_LIB_ITEM_STRUCT_TYPE;
    DrawLibItem -> Multi = Multi;
    DrawLibItem -> PartNameOrient =
    DrawLibItem -> ChipNameOrient = TEXT_ORIENT_NON;
    DrawLibItem -> ChipName = strdup(Name);
    DrawLibItem -> PartName = NULL;
    DrawLibItem -> PosX = DrawLibItem -> PosY = -20000;
    GEN_COPY(DrawLibItem -> Transform, TransMat, sizeof(int) * 4);

    PutCursorInActiveWindow();
    IntrSetIdleFunction(AutoPanActiveWindow);

    /* Place the part in its exact place and update part and chip names. */
    if (!PlaceLibItem(DrawLibItem)) {
	MyFree((VoidPtr) DrawLibItem);
    	IntrSetIdleFunction(NULL);
	return NULL;
    }

    IntrSetIdleFunction(NULL);

    /* Update the BBox knowledge: */
    DrawLibItem -> BBoxMinX = DrawLibItem -> PosX + Entry -> BBoxMinX;
    DrawLibItem -> BBoxMaxX = DrawLibItem -> PosX + Entry -> BBoxMaxX;
    DrawLibItem -> BBoxMinY = DrawLibItem -> PosY + Entry -> BBoxMinY;
    DrawLibItem -> BBoxMaxY = DrawLibItem -> PosY + Entry -> BBoxMaxY;

    DrawLibPart(DrawLibItem, GR_COPY_PUT, 1);

    /* Put the structure in the global object list, so automatic panning     */
    /* will draw it as well. It will be removed from EEDrawList before exit. */
    DrawLibItem -> Pnext = EEActiveWindow -> EEDrawList;
    EEActiveWindow -> EEDrawList = (DrawGenericStruct *) DrawLibItem;

    PopPosition = GRMapX(DrawLibItem -> PosX) < GRScreenMaxX / 2 ?
							INTR_WNDW_PLACE_RIGHT :
							INTR_WNDW_PLACE_LEFT;

    Cursor.CursorType = INTR_CURSOR_ARROW;

    if (Entry -> DrawName &&
	IntrQueryYesNo("Display chip name?", EEPopUpFrameColor,
		       EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
                       EEWindowsFrameWidth, &Cursor, PopPosition)) {
	DrawLibItem -> ChipNameX = DrawLibItem -> PosX;
	DrawLibItem -> ChipNameY = DrawLibItem -> PosY;
	if (!PlaceString(DrawLibItem -> ChipName,
			 &DrawLibItem -> ChipNameOrient,
			 1,
			 &DrawLibItem -> ChipNameX,
			 &DrawLibItem -> ChipNameY,
                         PopPosition)) {
	    EEActiveWindow -> EEDrawList =       /* Remove from global list. */
                EEActiveWindow -> EEDrawList -> Pnext;
	    DrawLibPart(DrawLibItem, GR_COPY_PUT, 0);
	    MyFree((VoidPtr) DrawLibItem -> ChipName);
	    MyFree((VoidPtr) DrawLibItem);
	    return NULL;
	}
    }

    DrawLibPart(DrawLibItem, GR_COPY_PUT, 1);

    strcpy(Line, Entry -> Prefix);

    Cursor.CursorType = INTR_CURSOR_ARROW;

    if (strlen(Entry -> Prefix) > 0 &&
	IntrQueryYesNo("Display part name?", EEPopUpFrameColor,
                       EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
                       EEWindowsFrameWidth, &Cursor, PopPosition) &&
	strlen(IntrQueryLine("Part name:", Line, LINE_LEN - 1,
        		     EEPopUpFrameColor, EEPopUpBackColor,
                             EEPopUpForeColor, EEWindowsFrameWidth,
                             PopPosition)) > 0) {
	
	/* DrawLibItem -> PartName = strdup(Line); */

if (Entry -> NumOfUnits > 1 & EESubName == TRUE) 
	sprintf(L2,"%s (%d)",Line,Multi);
else
	sprintf(L2,"%s",Line);
	DrawLibItem -> PartName = strdup(L2);

	DrawLibItem -> PartNameX = DrawLibItem -> PosX;
	DrawLibItem -> PartNameY = DrawLibItem -> PosY;
	if (!PlaceString(DrawLibItem -> PartName,
			 &DrawLibItem -> PartNameOrient,
			 1,
			 &DrawLibItem -> PartNameX,
			 &DrawLibItem -> PartNameY,
                         PopPosition)) {
	    if (DrawLibItem -> ChipName)
		MyFree((VoidPtr) DrawLibItem -> ChipName);
	    EEActiveWindow -> EEDrawList =	 /* Remove from global list. */
                EEActiveWindow -> EEDrawList -> Pnext;
	    DrawLibPart(DrawLibItem, GR_COPY_PUT, 0);
	    MyFree((VoidPtr) DrawLibItem -> PartName);
	    MyFree((VoidPtr) DrawLibItem);
	    return NULL;
	}
    }

    DrawLibPart(DrawLibItem, GR_COPY_PUT, 1);

    EEActiveWindow -> EEDrawList =
        EEActiveWindow -> EEDrawList -> Pnext;   /* Remove from global list. */
    DrawLibItem -> Pnext = NULL;

    return (DrawGenericStruct *) DrawLibItem;
}

/*****************************************************************************
* Routine to reposition a library item.					     *
*****************************************************************************/
BooleanType RePosLibItem(DrawLibItemStruct *DrawLibItem, int PopPosition)
{
    BooleanType Transform,
	RetVal = FALSE;
    int TempR, *TransMat[2], TempMat[2][2];

    /* Prepare the transformation information: */
    TransMat[0] = DrawLibItem -> Transform[0];
    TransMat[1] = DrawLibItem -> Transform[1];

    Cursor.CursorType = INTR_CURSOR_ARROW;

    if (TransPopUpMenu == NULL) TransPopUpMenu =
        IntrPopUpMenuCreate("Transform", (char **) TransformStrs, 0,
        		    TRANS_MENU_SIZE, EEPopUpFrameColor,
                            EEPopUpBackColor, EEPopUpForeColor,
                            EEPopUpXorColor, EEWindowsFrameWidth, &Cursor);

    while (TRUE) {
	if (!IntrPopUpMenu(TransPopUpMenu, PopPosition))
	    return RetVal;

        Transform = TRUE;
	switch (TransPopUpMenu -> SelectedIndex) {
	    case 0:
		return RetVal;
	    case 2:
		TempMat[0][0] = TempMat[1][1] = 0.0;
		TempMat[0][1] = 1.0;
		TempMat[1][0] = -1.0;
		break;
	    case 3:
		TempMat[0][0] = TempMat[1][1] = 0.0;
		TempMat[0][1] = -1.0;
		TempMat[1][0] = 1.0;
		break;
	    case 4:
		TempMat[0][0] = 1.0;
		TempMat[1][1] = -1.0;
		TempMat[0][1] = TempMat[1][0] = 0.0;
		break;
	    case 5:
		TempMat[0][0] = -1.0;
		TempMat[1][1] = 1.0;
		TempMat[0][1] = TempMat[1][0] = 0.0;
		break;
	    default:
		Transform = FALSE;
		break;
	}
	if (Transform) {
	    DrawLibPart(DrawLibItem, GR_COPY_PUT, 0);

	    TempR = TransMat[0][0] * TempMat[0][0] +
						TransMat[0][1] * TempMat[1][0];
	    TransMat[0][1] = TransMat[0][0] * TempMat[0][1] +
						TransMat[0][1] * TempMat[1][1];
	    TransMat[0][0] = TempR;
	    TempR = TransMat[1][0] * TempMat[0][0] +
						TransMat[1][1] * TempMat[1][0];
	    TransMat[1][1] = TransMat[1][0] * TempMat[0][1] +
						TransMat[1][1] * TempMat[1][1];
	    TransMat[1][0] = TempR;

	    DrawLibPart(DrawLibItem, GR_COPY_PUT, 1);

            RetVal = TRUE;
	}
    }
}

/*****************************************************************************
* Routine to place a library item. Return FALSE if ABORT signaled.	     *
*****************************************************************************/
BooleanType PlaceLibItem(DrawLibItemStruct *DrawLibItem)
{
    int Event, NewPosX, NewPosY, OldPosX, OldPosY, Dx, Dy;
    char Line[LINE_LEN_SHORT];
    LibraryEntryStruct *Entry;

    Cursor.CursorType = INTR_CURSOR_ARROW;

    if ((Entry = FindLibPart(DrawLibItem -> ChipName)) == NULL) {
	sprintf(Line, "Failed to find part \"%s\" in library",
						DrawLibItem -> ChipName);
	IntrQueryContinue(Line, EEPopUpFrameColor,
        		  EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
                          EEWindowsFrameWidth, &Cursor, INTR_WNDW_PLACE_CENTER);
	return FALSE;
    }
    IntrPushCursorType();
    Cursor.CursorType = INTR_CURSOR_CUSTOM;
    Cursor.CursorRoutine = DrawingEntryCursor;
    IntrSetCursorType(&Cursor);

    CrsrDrawLibItem = DrawLibItem;
    CrsrLibEntry = Entry;
    if (DrawLibItem -> PosX == -20000) {	    /* First time placement. */
	DrawLibItem -> PosX = EE_SNAP(GRInvMapX((EEActiveBBox -> Xmin +
						 EEActiveBBox -> Xmax) / 2));
	DrawLibItem -> PosY = EE_SNAP(GRInvMapY((EEActiveBBox -> Ymin +
						 EEActiveBBox -> Ymax) / 2));
    }
    GRCurrentCursorX = GRMapX(DrawLibItem -> PosX);
    GRCurrentCursorY = GRMapY(DrawLibItem -> PosY);
    sprintf(Line, "Place part \"%s\"", DrawLibItem -> ChipName);
    IntrDrawMessage(Line, EEPopUpForeColor, EEPopUpBackColor);

    OldPosX = DrawLibItem -> PosX;
    OldPosY = DrawLibItem -> PosY;

    if ((Event = IntrGetEventWaitSA(&NewPosX, &NewPosY)) == INTR_EVNT_SELECT) {
    	DrawLibItem -> PosX = GRInvMapX(NewPosX);
	DrawLibItem -> PosY = GRInvMapY(NewPosY);
	DrawLibItem -> PosX = EE_SNAP(DrawLibItem -> PosX);
	DrawLibItem -> PosY = EE_SNAP(DrawLibItem -> PosY);
	Dx = DrawLibItem -> PosX - OldPosX;
	Dy = DrawLibItem -> PosY - OldPosY;
	DrawLibItem -> PartNameX += Dx;
	DrawLibItem -> PartNameY += Dy;
	DrawLibItem -> ChipNameX += Dx;
	DrawLibItem -> ChipNameY += Dy;
	DrawLibItem -> BBoxMinX += Dx;
	DrawLibItem -> BBoxMinY += Dy;
	DrawLibItem -> BBoxMaxX += Dx;
	DrawLibItem -> BBoxMaxY += Dy;
    }

    IntrEraseMessage();

    IntrPopCursorType();
    Cursor.CursorType = INTR_CURSOR_ARROW;

    return Event != INTR_EVNT_ABORT;
}

/*****************************************************************************
* Routine to display an outline version of given library entry.		     *
* This routine is applied by the LibCreateNewpart routine above.	     *
*****************************************************************************/
static void DrawingEntryCursor(int PartX, int PartY)
{
    int i, x1, y1, x2, y2, PinWidth,
	y, MapX1, MapY1, MapX2, MapY2, TransMat[2][2],
        LastColor = GRGetColor();
    LibraryDrawEntryStruct *DEntry;

    /* Map from screen coords. to drawing coords. and offset as required. */
    GRSetColor(EE_HIGHLIGHT_COLOR);

    PartX = GRInvMapX(PartX);
    PartY = GRInvMapY(PartY);

    GEN_COPY(TransMat, CrsrDrawLibItem -> Transform, sizeof(int) * 4);

    if (CrsrLibEntry -> Drawings != NULL) {
	DEntry = CrsrLibEntry -> Drawings;
	while (DEntry != NULL) {
	    switch (DEntry -> DrawType) {
		case ARC_DRAW_TYPE:
		case CIRCLE_DRAW_TYPE:
		case TEXT_DRAW_TYPE:
		    break;
		case SQUARE_DRAW_TYPE:
		    x1 = PartX + TransMat[0][0] * DEntry -> U.Sqr.x1
			       + TransMat[0][1] * DEntry -> U.Sqr.y1;
		    y1 = PartY + TransMat[1][0] * DEntry -> U.Sqr.x1
			       + TransMat[1][1] * DEntry -> U.Sqr.y1;
		    x2 = PartX + TransMat[0][0] * DEntry -> U.Sqr.x2
			       + TransMat[0][1] * DEntry -> U.Sqr.y2;
		    y2 = PartY + TransMat[1][0] * DEntry -> U.Sqr.x2
			       + TransMat[1][1] * DEntry -> U.Sqr.y2;
		    GRMoveTo(x1, y1);
		    GRLineTo(x1, y2);
		    GRLineTo(x2, y2);
		    GRLineTo(x2, y1);
		    GRLineTo(x1, y1);
		    break;
		case LINE_DRAW_TYPE:
		    GRMoveTo(x1 = PartX + TransMat[0][0] * DEntry -> U.Line.x1
					+ TransMat[0][1] * DEntry -> U.Line.y1,
			     y1 = PartY + TransMat[1][0] * DEntry -> U.Line.x1
					+ TransMat[1][1] * DEntry -> U.Line.y1);
		    GRLineTo(x2 = PartX + TransMat[0][0] * DEntry -> U.Line.x2
					+ TransMat[0][1] * DEntry -> U.Line.y2,
			     y2 = PartY + TransMat[1][0] * DEntry -> U.Line.x2
					+ TransMat[1][1] * DEntry -> U.Line.y2);
		    break;
		case POLYLINE_DRAW_TYPE:
		    GRMoveTo(PartX +
			TransMat[0][0] * DEntry -> U.Poly.PolyList[0] +
			TransMat[0][1] * DEntry -> U.Poly.PolyList[1],
			     PartY +
			TransMat[1][0] * DEntry -> U.Poly.PolyList[0] +
			TransMat[1][1] * DEntry -> U.Poly.PolyList[1]);
		    for (i = 1; i < DEntry -> U.Poly.n; i++)
			GRLineTo(PartX +
			    TransMat[0][0] * DEntry -> U.Poly.PolyList[i * 2] +
			    TransMat[0][1] * DEntry -> U.Poly.PolyList[i * 2 + 1],
				 PartY +
			    TransMat[1][0] * DEntry -> U.Poly.PolyList[i * 2] +
			    TransMat[1][1] * DEntry -> U.Poly.PolyList[i * 2 + 1]);
		    break;
	    }
	    DEntry = DEntry -> Pnext;
	}
    }
    else {		  /* NULL Drawing - draw simple a box with all pins: */
	y1 = CrsrLibEntry -> TextInside ?
	    PIN_WIDTH * CrsrLibEntry -> NumOfPins / 4 :
	    PIN_WIDTH * CrsrLibEntry -> NumOfPins / 2;
	x1 = CrsrLibEntry -> TextInside ? (int) (y1 * CHIP_BOX_ASPECT_TI) :
					  (int) (y1 * CHIP_BOX_ASPECT_TO);
        /* But make sure we can still print somethings inside... */
	if (x1 < DRAW_TEXT_WIDTH * 12) x1 = DRAW_TEXT_WIDTH * 12;
	x2 = x1 / 2;
	y2 = y1 / 2;
	x1 = -x2;
	y1 = -y2;
	PinWidth = CrsrLibEntry -> TextInside ? PIN_WIDTH / 2 : PIN_WIDTH;

	GRMoveTo(PartX + TransMat[0][0] * x1 + TransMat[0][1] * y1,
		 PartY + TransMat[1][0] * x1 + TransMat[1][1] * y1);
	GRLineTo(PartX + TransMat[0][0] * x1 + TransMat[0][1] * y2,
		 PartY + TransMat[1][0] * x1 + TransMat[1][1] * y2);
	GRLineTo(PartX + TransMat[0][0] * x2 + TransMat[0][1] * y2,
		 PartY + TransMat[1][0] * x2 + TransMat[1][1] * y2);
	GRLineTo(PartX + TransMat[0][0] * x2 + TransMat[0][1] * y1,
		 PartY + TransMat[1][0] * x2 + TransMat[1][1] * y1);
	GRLineTo(PartX + TransMat[0][0] * x1 + TransMat[0][1] * y1,
		 PartY + TransMat[1][0] * x1 + TransMat[1][1] * y1);
	for (i = 0; i < CrsrLibEntry -> NumOfPins / 2; i++) {
	    y = y2 - PinWidth / 2 - i * PinWidth;
	    MapX1 = PartX + TransMat[0][0] * x1 + TransMat[0][1] * y;
	    MapY1 = PartY + TransMat[1][0] * x1 + TransMat[1][1] * y;
	    MapX2 = PartX + TransMat[0][0] * (x1 - PIN_LENGTH) + TransMat[0][1] * y;
	    MapY2 = PartY + TransMat[1][0] * (x1 - PIN_LENGTH) + TransMat[1][1] * y;
	    GRMoveTo(MapX1, MapY1);
	    GRLineTo(MapX2, MapY2);
	}
	for (i = CrsrLibEntry -> NumOfPins / 2 + 1;
	     i <= CrsrLibEntry -> NumOfPins;
	     i++) {
	    y = y1 + PinWidth / 2 + (i - CrsrLibEntry -> NumOfPins / 2 - 1) *
								PinWidth;
	    MapX1 = PartX + TransMat[0][0] * x2 + TransMat[0][1] * y;
	    MapY1 = PartY + TransMat[1][0] * x2 + TransMat[1][1] * y;
	    MapX2 = PartX + TransMat[0][0] * (x2 + PIN_LENGTH) + TransMat[0][1] * y;
	    MapY2 = PartY + TransMat[1][0] * (x2 + PIN_LENGTH) + TransMat[1][1] * y;
	    GRMoveTo(MapX1, MapY1);
	    GRLineTo(MapX2, MapY2);
	}
    }
    GRSetColor(LastColor);
}

/*****************************************************************************
* Returns TRUE iff the given library item chip name is drawable.	     *
*****************************************************************************/
BooleanType CanDrawChipName(char *LibName)
{
    char Line[LINE_LEN_SHORT];
    LibraryEntryStruct *Entry;

    if ((Entry = FindLibPart(LibName)) == NULL) {
	sprintf(Line, "Failed to find part \"%s\" in library", LibName);
    	IntrQueryContinue(Line, EEPopUpFrameColor,
        		  EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
                          EEWindowsFrameWidth, &Cursor, INTR_WNDW_PLACE_CENTER);
	return FALSE;
    }
    return Entry -> DrawName;
}
