home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * 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 <string.h>
- #include <time.h>
-
- #ifdef __MSDOS__
- #include <stdlib.h>
- #include <conio.h>
- #include <dos.h>
- #include <alloc.h>
- #endif /* __MSDOS__ */
-
- #include "program.h"
- #include "priorque.h"
- #include "eelibs.h"
- #include "eelibsl.h"
- #include "EELayer.h"
- #include "eeredraw.h"
- #include "eestring.h"
- #include "igraph.h"
- #include "primary.h"
-
- enum {
- TMENU_NONE = 10,
- TMENU_ROTATE_R,
- TMENU_ROTATE_L,
- TMENU_MIRROR_X,
- TMENU_MIRROR_Y
- };
-
- static void DrawLibPartAux(LibraryEntryStruct *Entry, int PartX, int PartY,
- int TransMat[2][2], int Multi);
- static char *LookUpPinText(char *Pins, int PinNum);
- static void MapAngles(int *Angle1, int *Angle2, int TransMat[2][2]);
- static LibraryEntryStruct *FindLibPart(char *Name);
-
- /*****************************************************************************
- * 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)
- {
- LibraryEntryStruct *Entry;
- char Line[LINE_LEN];
-
- if ((Entry = FindLibPart(DrawLibItem -> ChipName)) == NULL) {
- sprintf(Line, "Failed to find part \"%s\" in library",
- DrawLibItem -> ChipName);
- FatalError(Line);
- }
-
- DrawLibPartAux(Entry,
- DrawLibItem -> PosX,
- DrawLibItem -> PosY,
- DrawLibItem -> Transform,
- DrawLibItem -> Multi);
-
- if (Entry -> DrawName &&
- DrawLibItem -> ChipNameOrient != TEXT_ORIENT_NON)
- PutTextInfo(DrawLibItem -> ChipNameOrient,
- DrawLibItem -> ChipNameX,
- DrawLibItem -> ChipNameY,
- 1,
- DrawLibItem -> ChipName);
- if (DrawLibItem -> PartNameOrient != TEXT_ORIENT_NON)
- 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 = (LibraryEntryStruct *) PQFind(Lib -> Entries,
- (VoidPtr) &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 i, x1, y1, x2, y2, IsMulti, *NextPinMulti, NextPinNum, t1, t2,
- y, MapX1, MapY1, MapX2, MapY2, PinWidth, *Poly;
- char Line[LINE_LEN], *NextPinText;
- LibraryDrawEntryStruct *DEntry;
-
- 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))
- break;
- t1 = DEntry -> U.Arc.t1;
- t2 = DEntry -> U.Arc.t2;
- MapAngles(&t1, &t2, TransMat);
- IGArc(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))
- break;
- IGCircle(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))
- break;
-
- /* 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 !=
- TEXT_ORIENT_HORIZ);
- 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 ? TEXT_ORIENT_HORIZ : TEXT_ORIENT_VERT,
- x1, y1, 1, DEntry -> U.Text.Text);
- break;
- case SQUARE_DRAW_TYPE:
- if(!ReturnLayerMode(DEntry->Layer))
- break;
- 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;
- IGMoveTo(x1, y1);
- IGLineTo(x1, y2);
- IGLineTo(x2, y2);
- IGLineTo(x2, y1);
- IGLineTo(x1, y1);
- break;
- case LINE_DRAW_TYPE:
- if(!ReturnLayerMode(DEntry->Layer))
- break;
- 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);
- IGCircle(MapX1 * INVERT_PIN_RADIUS + x1,
- MapY1 * INVERT_PIN_RADIUS + y1,
- INVERT_PIN_RADIUS);
- IGMoveTo(MapX1 * INVERT_PIN_RADIUS * 2 + x1,
- MapY1 * INVERT_PIN_RADIUS * 2 + y1);
- IGLineTo(x2, y2);
- }
- else {
- IGMoveTo(x1, y1);
- IGLineTo(x2, y2);
- }
- if (IsMulti & ReturnLayerMode(LAYER_PIN)) {
- PutLineTextInfo(x1, y1, x2, y2,
- LookUpPinText(Entry -> Pins, *NextPinMulti),
- *NextPinMulti,
- Entry -> TextInside,
- Entry -> DrawNums);
- NextPinMulti++;
- }
- else {
- PutLineTextInfo(x1, y1, x2, y2,
- NextPinText,
- NextPinNum,
- Entry -> TextInside,
- Entry -> DrawNums);
- NextPinText = strtok(NULL, PIN_SEPERATOR);
- NextPinNum++;
- }
- break;
- case POLYLINE_DRAW_TYPE:
- if(!ReturnLayerMode(DEntry->Layer))
- break;
- 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];
- }
- IGPoly(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;
- if(ReturnLayerMode(LAYER_GATE)){
- IGMoveTo(PartX + TransMat[0][0] * x1 + TransMat[0][1] * y1,
- PartY + TransMat[1][0] * x1 + TransMat[1][1] * y1);
- IGLineTo(PartX + TransMat[0][0] * x1 + TransMat[0][1] * y2,
- PartY + TransMat[1][0] * x1 + TransMat[1][1] * y2);
- IGLineTo(PartX + TransMat[0][0] * x2 + TransMat[0][1] * y2,
- PartY + TransMat[1][0] * x2 + TransMat[1][1] * y2);
- IGLineTo(PartX + TransMat[0][0] * x2 + TransMat[0][1] * y1,
- PartY + TransMat[1][0] * x2 + TransMat[1][1] * y1);
- IGLineTo(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;
- IGMoveTo(MapX1, MapY1);
- IGLineTo(MapX2, MapY2);
- if (IsMulti & ReturnLayerMode(LAYER_PINNUM)) {
- PutLineTextInfo(MapX1, MapY1, MapX2, MapY2,
- LookUpPinText(Entry -> Pins, *NextPinMulti),
- *NextPinMulti,
- Entry -> TextInside,
- Entry -> DrawNums);
- NextPinMulti++;
- }
- else if(ReturnLayerMode(LAYER_PINNUM)) {
- PutLineTextInfo(MapX1, MapY1, MapX2, MapY2,
- NextPinText,
- NextPinNum,
- Entry -> TextInside,
- Entry -> DrawNums);
- 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;
- if(ReturnLayerMode(LAYER_GATE)){
- IGMoveTo(MapX1, MapY1);
- IGLineTo(MapX2, MapY2);
- }
- if (IsMulti & ReturnLayerMode(LAYER_PINNUM)) {
- PutLineTextInfo(MapX1, MapY1, MapX2, MapY2,
- LookUpPinText(Entry -> Pins, *NextPinMulti),
- *NextPinMulti,
- Entry -> TextInside,
- Entry -> DrawNums);
- NextPinMulti++;
- }
- else if(ReturnLayerMode(LAYER_PINNUM)) {
- PutLineTextInfo(MapX1, MapY1, MapX2, MapY2,
- NextPinText,
- NextPinNum,
- Entry -> TextInside,
- Entry -> DrawNums);
- NextPinText = strtok(NULL, PIN_SEPERATOR);
- NextPinNum++;
- }
- }
- }
- }
-
- /*****************************************************************************
- * 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;
- }
-