home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / GRAPHICS / MISC / EEDRW23S.ZIP / EELIBS2.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-20  |  53.9 KB  |  1,529 lines

  1. /*****************************************************************************
  2. *   Module to handle libraries (second part - drawing and interaction).         *
  3. *                                         *
  4. * Written by:  Gershon Elber            IBM PC Ver 1.0,    Oct. 1989    *
  5. *****************************************************************************/
  6.  
  7. #include <math.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <conio.h>
  11. #include <string.h>
  12. #include <dos.h>
  13. #include <dir.h>
  14. #include <alloc.h>
  15. #include <time.h>
  16. #include "Program.h"
  17. #include "Director.h"
  18. #include "PriorQue.h"
  19. #include "EELibs.h"
  20. #include "EELibsL.h"
  21. #include "EECreate.h"
  22. #include "EELoad.h"
  23. #include "EEModify.h"
  24. #include "EERedraw.h"
  25. #include "EEString.h"
  26.  
  27. /* Used the hold cursor information for local cursor drawing routines. */
  28. static DrawLibItemStruct *CrsrDrawLibItem;
  29. static LibraryEntryStruct *CrsrLibEntry;
  30. static IntrCursorShapeStruct Cursor = {
  31.     INTR_CURSOR_ARROW, 0, 0, 0, 0, FALSE, NULL, FALSE
  32. };
  33.  
  34. static char *TransformStrs[] =
  35. {
  36.     "PlaceIt",
  37.     "",
  38.     "RotateR",
  39.     "RotateL",
  40.     "MirrorX",
  41.     "MirrorY",
  42. };
  43. #define TRANS_MENU_SIZE (sizeof(TransformStrs) / sizeof(char *))
  44.  
  45. static IntrPopUpMenuStruct
  46.     *TransPopUpMenu = NULL;
  47.  
  48. static void DrawLibPartAux(LibraryEntryStruct *Entry, int PartX, int PartY,
  49.     int TransMat[2][2], int Multi, int DrawMode, int Color);
  50. static void PushNetListItem(NetListStruct **NetList,
  51.                 int MapX1, int MapY1, int MapX2, int MapY2,
  52.                 char *PartName, char *ChipName, char *PinName,
  53.                 int PinNum);
  54. static char *LookUpPinText(char *Pins, int PinNum);
  55. static void MapAngles(int *Angle1, int *Angle2, int TransMat[2][2]);
  56. static void ViewOneLibrary(LibraryStruct *Lib);
  57. static LibraryEntryStruct *FindLibPart(char *Name);
  58. static void DrawingEntryCursor(int x, int y);
  59.  
  60. /*****************************************************************************
  61. * Routine to view library(ies) content.                         *
  62. *****************************************************************************/
  63. void ViewLibrary(void)
  64. {
  65.     int i, NumOfLibs = NumOfLibraries();
  66.     char **Names;
  67.     LibraryStruct *Lib;
  68.  
  69.     Cursor.CursorType = INTR_CURSOR_ARROW;
  70.  
  71.     if (NumOfLibs == 0) {
  72.     IntrQueryContinue("No libraries are loaded", EEPopUpFrameColor,
  73.                   EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
  74.                           EEWindowsFrameWidth, &Cursor,
  75.                           INTR_WNDW_PLACE_CENTER);
  76.  
  77.     return;
  78.     }
  79.     Names = (char **) MyMalloc(sizeof(char *) * NumOfLibs);
  80.     for (i = 0, Lib = LibraryList; Lib != NULL; Lib = Lib -> Pnext, i++) {
  81.     Names[i] = Lib -> Name;
  82.     }
  83.     do {
  84.     i = IntrQueryList("View Libs", (char **) Names, 0, NumOfLibs,
  85.               EEListNumDisplayed, EEPopUpFrameColor,
  86.                           EEPopUpBackColor, EEPopUpForeColor,
  87.                           EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  88.                           INTR_WNDW_PLACE_CENTER);
  89.     if (i >= 0) {
  90.             IntrWndwPop(EERootWindowID, TRUE, FALSE);
  91.  
  92.         for (Lib = LibraryList; i > 0; i--, Lib = Lib -> Pnext);
  93.         ViewOneLibrary(Lib);
  94.  
  95.             IntrWndwPush(EERootWindowID, TRUE);
  96.     }
  97.     }
  98.     while (i >= 0);
  99.  
  100.     MyFree((VoidPtr) Names);
  101. }
  102.  
  103. /*****************************************************************************
  104. * Routine to draw the given part at given position, transformed/mirror as    *
  105. * specified, and in the given drawing mode. Only this one is visible...         *
  106. *****************************************************************************/
  107. void DrawLibPart(DrawLibItemStruct *DrawLibItem, int DrawMode, int Color)
  108. {
  109.     LibraryEntryStruct *Entry;
  110.     char Line[LINE_LEN];
  111.  
  112.     GRSetLineStyle(GR_SOLID_LINE, 0, GR_NORM_WIDTH);
  113.  
  114.     Cursor.CursorType = INTR_CURSOR_ARROW;
  115.  
  116.     if ((Entry = FindLibPart(DrawLibItem -> ChipName)) == NULL) {
  117.     sprintf(Line, "Failed to find part \"%s\" in library",
  118.                         DrawLibItem -> ChipName);
  119.     IntrQueryContinue(Line, EEPopUpFrameColor,
  120.                   EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
  121.                           EEWindowsFrameWidth, &Cursor,
  122.                           INTR_WNDW_PLACE_CENTER);
  123.     return;
  124.     }
  125.  
  126.     DrawLibPartAux(Entry,
  127.            DrawLibItem -> PosX,
  128.            DrawLibItem -> PosY,
  129.            DrawLibItem -> Transform,
  130.            DrawLibItem -> Multi,
  131.            DrawMode,
  132.            Color);
  133.  
  134.     if (Entry -> DrawName &&
  135.     DrawLibItem -> ChipNameOrient != TEXT_ORIENT_NON)
  136.     PutTextInfo(DrawLibItem -> ChipNameOrient,
  137.             DrawLibItem -> ChipNameX,
  138.             DrawLibItem -> ChipNameY,
  139.             1,
  140.             DrawLibItem -> ChipName);
  141.     if (DrawLibItem -> PartNameOrient != TEXT_ORIENT_NON)
  142.     PutTextInfo(DrawLibItem -> PartNameOrient,
  143.             DrawLibItem -> PartNameX,
  144.             DrawLibItem -> PartNameY,
  145.             1,
  146.             DrawLibItem -> PartName);
  147. }
  148.  
  149. /*****************************************************************************
  150. * Routine to find a part in one of the libraries given its name.         *
  151. *****************************************************************************/
  152. static LibraryEntryStruct *FindLibPart(char *Name)
  153. {
  154.     LibraryEntryStruct *Entry, DummyEntry;
  155.     LibraryStruct
  156.     *Lib = LibraryList;
  157.  
  158.     DummyEntry.Pins = NULL;            /* Used only to call PQFind. */
  159.     DummyEntry.Drawings = NULL;
  160.     DummyEntry.Multi = NULL;
  161.     strcpy(DummyEntry.Name, Name);
  162.  
  163.     PQCompFunc((PQCompFuncType) LibraryEntryCompare);
  164.  
  165.     while (Lib) {
  166.     if ((Entry = PQFind(Lib -> Entries, &DummyEntry)) != NULL)
  167.         return Entry;
  168.  
  169.     Lib = Lib -> Pnext;
  170.     }
  171.     return NULL;
  172. }
  173.  
  174. /*****************************************************************************
  175. * Routine to draw the given part at given position, transformed/mirror as    *
  176. * specified, and in the given drawing mode.                     *
  177. *****************************************************************************/
  178. static void DrawLibPartAux(LibraryEntryStruct *Entry, int PartX, int PartY,
  179.     int TransMat[2][2], int Multi, int DrawMode, int Color)
  180. {
  181.     int i, x1, y1, x2, y2, IsMulti, *NextPinMulti, NextPinNum, t1, t2,
  182.     y, MapX1, MapY1, MapX2, MapY2, PinWidth, *Poly;
  183.     char Line[LINE_LEN], *NextPinText;
  184.     LibraryDrawEntryStruct *DEntry;
  185.  
  186.     GRSetFillStyle(GR_SOLID_FILL, Color);
  187.     GRSetWriteMode(DrawMode);
  188.     GRSetColor(Color);
  189.  
  190.     IsMulti = Entry -> NumOfUnits > 0;
  191.     if (IsMulti) {
  192.     /* Make NextMulti point on next pin number in multi array: */
  193.     NextPinMulti = &Entry -> Multi[Entry -> PinsPerUnit * --Multi];
  194.  
  195.     NextPinText = NULL;
  196.     }
  197.     else {
  198.     NextPinNum = 1;
  199.     NextPinMulti = NULL;
  200.  
  201.     /* Make a copy of all pin text info so we can use strtok routine on: */
  202.     strncpy(Line, Entry -> Pins, LINE_LEN - 1);
  203.     NextPinText = strtok(Line, PIN_SEPERATOR);
  204.     }
  205.  
  206.     if (Entry -> Drawings != NULL) {
  207.     DEntry = Entry -> Drawings;
  208.     while (DEntry != NULL) {
  209.         switch (DEntry -> DrawType) {
  210.         case ARC_DRAW_TYPE:
  211.             t1 = DEntry -> U.Arc.t1;
  212.             t2 = DEntry -> U.Arc.t2;
  213.             MapAngles(&t1, &t2, TransMat);
  214.             GRArc(PartX + TransMat[0][0] * DEntry -> U.Arc.x +
  215.                   TransMat[0][1] * DEntry -> U.Arc.y,
  216.               PartY + TransMat[1][0] * DEntry -> U.Arc.x +
  217.                   TransMat[1][1] * DEntry -> U.Arc.y,
  218.               t1,
  219.               t2,
  220.               DEntry -> U.Arc.r);
  221.             break;
  222.         case CIRCLE_DRAW_TYPE:
  223.             GRCircle(PartX + TransMat[0][0] * DEntry -> U.Circ.x +
  224.                      TransMat[0][1] * DEntry -> U.Circ.y,
  225.                  PartY + TransMat[1][0] * DEntry -> U.Circ.x +
  226.                      TransMat[1][1] * DEntry -> U.Circ.y,
  227.                  DEntry -> U.Circ.r);
  228.             break;
  229.         case TEXT_DRAW_TYPE:
  230.             /* The text orientation may need to be flipped if the    */
  231.             /* transformation matrix cuases xy axes to be flipped.   */
  232.             t1 = (TransMat[0][0] == 0) ^ (DEntry -> U.Text.Horiz != 0);
  233.             x1 = PartX + TransMat[0][0] * DEntry -> U.Text.x
  234.                    + TransMat[0][1] * DEntry -> U.Text.y;
  235.             y1 = PartY + TransMat[1][0] * DEntry -> U.Text.x
  236.                    + TransMat[1][1] * DEntry -> U.Text.y;
  237.             PutTextInfo(t1 ? GR_HORIZ_DIR : GR_VERT_DIR, x1, y1, 1,
  238.                 DEntry -> U.Text.Text);
  239.             break;
  240.         case SQUARE_DRAW_TYPE:
  241.             x1 = PartX + TransMat[0][0] * DEntry -> U.Sqr.x1
  242.                    + TransMat[0][1] * DEntry -> U.Sqr.y1;
  243.             y1 = PartY + TransMat[1][0] * DEntry -> U.Sqr.x1
  244.                    + TransMat[1][1] * DEntry -> U.Sqr.y1;
  245.             x2 = PartX + TransMat[0][0] * DEntry -> U.Sqr.x2
  246.                    + TransMat[0][1] * DEntry -> U.Sqr.y2;
  247.             y2 = PartY + TransMat[1][0] * DEntry -> U.Sqr.x2
  248.                    + TransMat[1][1] * DEntry -> U.Sqr.y2;
  249.             GRMoveTo(x1, y1);
  250.             GRLineTo(x1, y2);
  251.             GRLineTo(x2, y2);
  252.             GRLineTo(x2, y1);
  253.             GRLineTo(x1, y1);
  254.             break;
  255.         case LINE_DRAW_TYPE:
  256.             x1 = PartX + TransMat[0][0] * DEntry -> U.Line.x1
  257.                    + TransMat[0][1] * DEntry -> U.Line.y1;
  258.             y1 = PartY + TransMat[1][0] * DEntry -> U.Line.x1
  259.                    + TransMat[1][1] * DEntry -> U.Line.y1;
  260.             x2 = PartX + TransMat[0][0] * DEntry -> U.Line.x2
  261.                    + TransMat[0][1] * DEntry -> U.Line.y2;
  262.             y2 = PartY + TransMat[1][0] * DEntry -> U.Line.x2
  263.                    + TransMat[1][1] * DEntry -> U.Line.y2;
  264.             if (DEntry -> U.Line.Invert) {
  265.             MapX1 = SIGN(x2 - x1);
  266.             MapY1 = SIGN(y2 - y1);
  267.             GRCircle(MapX1 * INVERT_PIN_RADIUS + x1,
  268.                  MapY1 * INVERT_PIN_RADIUS + y1,
  269.                  INVERT_PIN_RADIUS);
  270.             GRMoveTo(MapX1 * INVERT_PIN_RADIUS * 2 + x1,
  271.                  MapY1 * INVERT_PIN_RADIUS * 2 + y1);
  272.             GRLineTo(x2, y2);
  273.             }
  274.             else {
  275.             GRMoveTo(x1, y1);
  276.             GRLineTo(x2, y2);
  277.             }
  278.             if (IsMulti) {
  279.             PutLineTextInfo(x1, y1, x2, y2,
  280.                 LookUpPinText(Entry -> Pins, *NextPinMulti),
  281.                 *NextPinMulti,
  282.                 Entry -> TextInside,
  283.                 Entry -> DrawNums);
  284.             NextPinMulti++;
  285.             }
  286.             else {
  287.             PutLineTextInfo(x1, y1, x2, y2,
  288.                 NextPinText,
  289.                 NextPinNum,
  290.                 Entry -> TextInside,
  291.                 Entry -> DrawNums);
  292.             NextPinText = strtok(NULL, PIN_SEPERATOR);
  293.             NextPinNum++;
  294.             }
  295.             break;
  296.         case POLYLINE_DRAW_TYPE:
  297.             Poly = (int *) MyMalloc(sizeof(int) * 2 *
  298.                             DEntry -> U.Poly.n);
  299.             for (i = 0; i < DEntry -> U.Poly.n; i++) {
  300.             Poly[i * 2] = PartX +
  301.                 TransMat[0][0] * DEntry -> U.Poly.PolyList[i * 2] +
  302.                 TransMat[0][1] * DEntry -> U.Poly.PolyList[i * 2 + 1];
  303.             Poly[i * 2 + 1] = PartY +
  304.                 TransMat[1][0] * DEntry -> U.Poly.PolyList[i * 2] +
  305.                 TransMat[1][1] * DEntry -> U.Poly.PolyList[i * 2 + 1];
  306.             }
  307.             GRPoly(DEntry -> U.Poly.n, Poly, DEntry -> U.Poly.Fill);
  308.             MyFree((VoidPtr) Poly);
  309.             break;
  310.         }
  311.         DEntry = DEntry -> Pnext;
  312.     }
  313.     }
  314.     else {          /* NULL Drawing - draw simple a box with all pins: */
  315.     y1 = Entry -> TextInside ? PIN_WIDTH * Entry -> NumOfPins / 4 :
  316.                    PIN_WIDTH * Entry -> NumOfPins / 2;
  317.     x1 = Entry -> TextInside ? (int) (y1 * CHIP_BOX_ASPECT_TI) :
  318.                    (int) (y1 * CHIP_BOX_ASPECT_TO);
  319.     /* But make sure we can still print somethings inside... */
  320.     if (x1 < DRAW_TEXT_WIDTH * 12) x1 = DRAW_TEXT_WIDTH * 12;
  321.     x2 = x1 / 2;
  322.     y2 = y1 / 2;
  323.     x1 = -x2;
  324.     y1 = -y2;
  325.     PinWidth = Entry -> TextInside ? PIN_WIDTH / 2 : PIN_WIDTH;
  326.  
  327.     GRMoveTo(PartX + TransMat[0][0] * x1 + TransMat[0][1] * y1,
  328.          PartY + TransMat[1][0] * x1 + TransMat[1][1] * y1);
  329.     GRLineTo(PartX + TransMat[0][0] * x1 + TransMat[0][1] * y2,
  330.          PartY + TransMat[1][0] * x1 + TransMat[1][1] * y2);
  331.     GRLineTo(PartX + TransMat[0][0] * x2 + TransMat[0][1] * y2,
  332.          PartY + TransMat[1][0] * x2 + TransMat[1][1] * y2);
  333.     GRLineTo(PartX + TransMat[0][0] * x2 + TransMat[0][1] * y1,
  334.          PartY + TransMat[1][0] * x2 + TransMat[1][1] * y1);
  335.     GRLineTo(PartX + TransMat[0][0] * x1 + TransMat[0][1] * y1,
  336.          PartY + TransMat[1][0] * x1 + TransMat[1][1] * y1);
  337.     for (i = 0; i < Entry -> NumOfPins / 2; i++) {
  338.         y = y2 - PinWidth / 2 - i * PinWidth;
  339.         MapX1 = PartX + TransMat[0][0] * x1 + TransMat[0][1] * y;
  340.         MapY1 = PartY + TransMat[1][0] * x1 + TransMat[1][1] * y;
  341.         MapX2 = PartX + TransMat[0][0] * (x1 - PIN_LENGTH) + TransMat[0][1] * y;
  342.         MapY2 = PartY + TransMat[1][0] * (x1 - PIN_LENGTH) + TransMat[1][1] * y;
  343.         GRMoveTo(MapX1, MapY1);
  344.         GRLineTo(MapX2, MapY2);
  345.         if (IsMulti) {
  346.         PutLineTextInfo(MapX1, MapY1, MapX2, MapY2,
  347.             LookUpPinText(Entry -> Pins, *NextPinMulti),
  348.             *NextPinMulti,
  349.             Entry -> TextInside,
  350.             Entry -> DrawNums);
  351.         NextPinMulti++;
  352.         }
  353.         else {
  354.         PutLineTextInfo(MapX1, MapY1, MapX2, MapY2,
  355.             NextPinText,
  356.             NextPinNum,
  357.             Entry -> TextInside,
  358.             Entry -> DrawNums);
  359.         NextPinText = strtok(NULL, PIN_SEPERATOR);
  360.         NextPinNum++;
  361.         }
  362.     }
  363.     for (i = Entry -> NumOfPins / 2 + 1; i <= Entry -> NumOfPins; i++) {
  364.         y = y1 + PinWidth / 2 + (i - Entry -> NumOfPins / 2 - 1) *
  365.                                 PinWidth;
  366.         MapX1 = PartX + TransMat[0][0] * x2 + TransMat[0][1] * y;
  367.         MapY1 = PartY + TransMat[1][0] * x2 + TransMat[1][1] * y;
  368.         MapX2 = PartX + TransMat[0][0] * (x2 + PIN_LENGTH) + TransMat[0][1] * y;
  369.         MapY2 = PartY + TransMat[1][0] * (x2 + PIN_LENGTH) + TransMat[1][1] * y;
  370.         GRMoveTo(MapX1, MapY1);
  371.         GRLineTo(MapX2, MapY2);
  372.         if (IsMulti) {
  373.         PutLineTextInfo(MapX1, MapY1, MapX2, MapY2,
  374.             LookUpPinText(Entry -> Pins, *NextPinMulti),
  375.             *NextPinMulti,
  376.             Entry -> TextInside,
  377.             Entry -> DrawNums);
  378.         NextPinMulti++;
  379.         }
  380.         else {
  381.         PutLineTextInfo(MapX1, MapY1, MapX2, MapY2,
  382.             NextPinText,
  383.             NextPinNum,
  384.             Entry -> TextInside,
  385.             Entry -> DrawNums);
  386.         NextPinText = strtok(NULL, PIN_SEPERATOR);
  387.         NextPinNum++;
  388.         }
  389.     }
  390.     }
  391. }
  392.  
  393. /*****************************************************************************
  394. * Routine to find the closest connection point of the library item to the    *
  395. * given point and set ClosestX/Y to it.                         *
  396. * As the only connections are defined via LINE definition only those are     *
  397. * tested. More than that - only the second point entry of LINE is tested as  *
  398. * the first one is the connection to the object itself.                 *
  399. *****************************************************************************/
  400. void SnapLibItemPoint(int OrigX, int OrigY, int *ClosestX, int *ClosestY,
  401.                         DrawLibItemStruct *DrawLibItem)
  402. {
  403.     int i, TempX, TempY, TempY1, TransMat[2][2], PartX, PartY, *Points,
  404.     x1, y1, x2, y2, PinWidth;
  405.     unsigned int Dist;
  406.     char Line[LINE_LEN_SHORT];
  407.     LibraryEntryStruct *Entry;
  408.     LibraryDrawEntryStruct *DEntry;
  409.  
  410.     GEN_COPY(TransMat, DrawLibItem -> Transform, sizeof(int) * 4);
  411.     PartX = DrawLibItem -> PosX;
  412.     PartY = DrawLibItem -> PosY;
  413.     Dist = ((unsigned int) ABS(*ClosestX - OrigX)) +
  414.        ((unsigned int) ABS(*ClosestY - OrigY));
  415.  
  416.     Cursor.CursorType = INTR_CURSOR_ARROW;
  417.  
  418.     if ((Entry = FindLibPart(DrawLibItem -> ChipName)) == NULL) {
  419.     sprintf(Line, "Failed to find part \"%s\" in library",
  420.                         DrawLibItem -> PartName);
  421.     IntrQueryContinue(Line, EEPopUpFrameColor,
  422.               EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
  423.               EEWindowsFrameWidth, &Cursor,
  424.                           INTR_WNDW_PLACE_CENTER);
  425.     return;
  426.     }
  427.  
  428.     if (Entry -> Drawings != NULL) {
  429.     DEntry = Entry -> Drawings;
  430.     while (DEntry != NULL) {
  431.         switch (DEntry -> DrawType) {
  432.         case LINE_DRAW_TYPE:
  433.             TempX = PartX + TransMat[0][0] * DEntry -> U.Line.x1
  434.                     + TransMat[0][1] * DEntry -> U.Line.y1;
  435.             TempY = PartY + TransMat[1][0] * DEntry -> U.Line.x1
  436.                     + TransMat[1][1] * DEntry -> U.Line.y1;
  437.             if (((unsigned int) ABS(TempX - OrigX)) +
  438.             ((unsigned int) ABS(TempY - OrigY)) < Dist) {
  439.             *ClosestX = TempX;
  440.             *ClosestY = TempY;
  441.             Dist = ((unsigned int) ABS(TempX - OrigX)) +
  442.                    ((unsigned int) ABS(TempY - OrigY));
  443.             }
  444.             TempX = PartX + TransMat[0][0] * DEntry -> U.Line.x2
  445.                     + TransMat[0][1] * DEntry -> U.Line.y2;
  446.             TempY = PartY + TransMat[1][0] * DEntry -> U.Line.x2
  447.                     + TransMat[1][1] * DEntry -> U.Line.y2;
  448.             if (((unsigned int) ABS(TempX - OrigX)) +
  449.             ((unsigned int) ABS(TempY - OrigY)) < Dist) {
  450.             *ClosestX = TempX;
  451.             *ClosestY = TempY;
  452.             Dist = ((unsigned int) ABS(TempX - OrigX)) +
  453.                    ((unsigned int) ABS(TempY - OrigY));
  454.             }
  455.             break;
  456.         case SQUARE_DRAW_TYPE:
  457.             TempX = PartX + TransMat[0][0] * DEntry -> U.Sqr.x1
  458.                     + TransMat[0][1] * DEntry -> U.Sqr.y1;
  459.             TempY = PartY + TransMat[1][0] * DEntry -> U.Sqr.x1
  460.                     + TransMat[1][1] * DEntry -> U.Sqr.y1;
  461.             if (((unsigned int) ABS(TempX - OrigX)) +
  462.             ((unsigned int) ABS(TempY - OrigY)) < Dist) {
  463.             *ClosestX = TempX;
  464.             *ClosestY = TempY;
  465.             Dist = ((unsigned int) ABS(TempX - OrigX)) +
  466.                    ((unsigned int) ABS(TempY - OrigY));
  467.             }
  468.  
  469.             TempX = PartX + TransMat[0][0] * DEntry -> U.Sqr.x2
  470.                     + TransMat[0][1] * DEntry -> U.Sqr.y2;
  471.             TempY = PartY + TransMat[1][0] * DEntry -> U.Sqr.x2
  472.                     + TransMat[1][1] * DEntry -> U.Sqr.y2;
  473.             if (((unsigned int) ABS(TempX - OrigX)) +
  474.             ((unsigned int) ABS(TempY - OrigY)) < Dist) {
  475.             *ClosestX = TempX;
  476.             *ClosestY = TempY;
  477.             Dist = ((unsigned int) ABS(TempX - OrigX)) +
  478.                    ((unsigned int) ABS(TempY - OrigY));
  479.             }
  480.  
  481.             TempX = PartX + TransMat[0][0] * DEntry -> U.Sqr.x2
  482.                     + TransMat[0][1] * DEntry -> U.Sqr.y1;
  483.             TempY = PartY + TransMat[1][0] * DEntry -> U.Sqr.x2
  484.                     + TransMat[1][1] * DEntry -> U.Sqr.y1;
  485.             if (((unsigned int) ABS(TempX - OrigX)) +
  486.             ((unsigned int) ABS(TempY - OrigY)) < Dist) {
  487.             *ClosestX = TempX;
  488.             *ClosestY = TempY;
  489.             Dist = ((unsigned int) ABS(TempX - OrigX)) +
  490.                    ((unsigned int) ABS(TempY - OrigY));
  491.             }
  492.  
  493.             TempX = PartX + TransMat[0][0] * DEntry -> U.Sqr.x1
  494.                     + TransMat[0][1] * DEntry -> U.Sqr.y2;
  495.             TempY = PartY + TransMat[1][0] * DEntry -> U.Sqr.x1
  496.                     + TransMat[1][1] * DEntry -> U.Sqr.y2;
  497.             if (((unsigned int) ABS(TempX - OrigX)) +
  498.             ((unsigned int) ABS(TempY - OrigY)) < Dist) {
  499.             *ClosestX = TempX;
  500.             *ClosestY = TempY;
  501.             Dist = ((unsigned int) ABS(TempX - OrigX)) +
  502.                    ((unsigned int) ABS(TempY - OrigY));
  503.             }
  504.             break;
  505.         case POLYLINE_DRAW_TYPE:
  506.             Points = DEntry -> U.Poly.PolyList;
  507.             for (i = 0; i < DEntry -> U.Poly.n; i++) {
  508.             TempX = PartX + TransMat[0][0] * Points[i * 2]
  509.                       + TransMat[0][1] * Points[i * 2 + 1];
  510.             TempY = PartY + TransMat[1][0] * Points[i * 2]
  511.                       + TransMat[1][1] * Points[i * 2 + 1];
  512.  
  513.             if (((unsigned int) ABS(TempX - OrigX)) +
  514.                 ((unsigned int) ABS(TempY - OrigY)) < Dist) {
  515.                 *ClosestX = TempX;
  516.                 *ClosestY = TempY;
  517.                 Dist = ((unsigned int) ABS(TempX - OrigX)) +
  518.                    ((unsigned int) ABS(TempY - OrigY));
  519.             }
  520.             }
  521.             break;
  522.         case ARC_DRAW_TYPE:
  523.         case CIRCLE_DRAW_TYPE:
  524.         case TEXT_DRAW_TYPE:
  525.             break;
  526.         }
  527.         DEntry = DEntry -> Pnext;
  528.     }
  529.     }
  530.     else {                      /* Simple a box with all pins: */
  531.     y1 = Entry -> TextInside ? PIN_WIDTH * Entry -> NumOfPins / 4 :
  532.                    PIN_WIDTH * Entry -> NumOfPins / 2;
  533.     x1 = Entry -> TextInside ? (int) (y1 * CHIP_BOX_ASPECT_TI) :
  534.                    (int) (y1 * CHIP_BOX_ASPECT_TO);
  535.     /* But make sure we can still print somethings inside... */
  536.     if (x1 < DRAW_TEXT_WIDTH * 12) x1 = DRAW_TEXT_WIDTH * 12;
  537.     x2 = x1 / 2;
  538.     y2 = y1 / 2;
  539.     x1 = -x2;
  540.     y1 = -y2;
  541.     PinWidth = Entry -> TextInside ? PIN_WIDTH / 2 : PIN_WIDTH;
  542.  
  543.     for (i = 0; i < Entry -> NumOfPins / 2; i++) {
  544.         TempY1 = y2 - PinWidth / 2 - i * PinWidth;
  545.         TempX = PartX + TransMat[0][0] * (x1 - PIN_LENGTH) +
  546.                 TransMat[0][1] * TempY1;
  547.         TempY = PartY + TransMat[1][0] * (x1 - PIN_LENGTH) +
  548.                 TransMat[1][1] * TempY1;
  549.         if (((unsigned int) ABS(TempX - OrigX)) +
  550.         ((unsigned int) ABS(TempY - OrigY)) < Dist) {
  551.         *ClosestX = TempX;
  552.         *ClosestY = TempY;
  553.         Dist = ((unsigned int) ABS(TempX - OrigX)) +
  554.                ((unsigned int) ABS(TempY - OrigY));
  555.         }
  556.     }
  557.     for (i = Entry -> NumOfPins / 2 + 1; i <= Entry -> NumOfPins; i++) {
  558.         TempY1 = y1 + PinWidth / 2 + (i - Entry -> NumOfPins / 2 - 1) *
  559.                                 PinWidth;
  560.         TempX = PartX + TransMat[0][0] * (x2 + PIN_LENGTH) +
  561.                 TransMat[0][1] * TempY1;
  562.         TempY = PartY + TransMat[1][0] * (x2 + PIN_LENGTH) +
  563.                 TransMat[1][1] * TempY1;
  564.         if (((unsigned int) ABS(TempX - OrigX)) +
  565.         ((unsigned int) ABS(TempY - OrigY)) < Dist) {
  566.         *ClosestX = TempX;
  567.         *ClosestY = TempY;
  568.         Dist = ((unsigned int) ABS(TempX - OrigX)) +
  569.                ((unsigned int) ABS(TempY - OrigY));
  570.         }
  571.     }
  572.     }
  573. }
  574.  
  575. /*****************************************************************************
  576. * Routine to find all pins that have connection to the line from x1/y1 to    *
  577. * x2/y2 in Library item provided. Only terminals (LINE_DRAW_TYPE) are tested.*
  578. *****************************************************************************/
  579. NetListStruct *FindLibItemNetList(int lx1, int ly1, int lx2, int ly2,
  580.                   BooleanType l1Bus,
  581.                   DrawGenericStruct *Phead,
  582.                   DrawLibItemStruct *DrawLibItem)
  583. {
  584.     int i, j, IsMulti, Multi, *NextPinMulti, TransMat[2][2], PartX, PartY,
  585.     NextPinNum, PinWidth, y, x1, y1, x2, y2, MapX1, MapY1, MapX2, MapY2;
  586.     char *p, *NextPinText, Line[LINE_LEN];
  587.     LibraryEntryStruct *Entry;
  588.     LibraryDrawEntryStruct *DEntry;
  589.     NetListStruct
  590.     *NetList = NULL;
  591.  
  592.     GEN_COPY(TransMat, DrawLibItem -> Transform, sizeof(int) * 4);
  593.     PartX = DrawLibItem -> PosX;
  594.     PartY = DrawLibItem -> PosY;
  595.     Multi = DrawLibItem -> Multi;
  596.  
  597.     if ((Entry = FindLibPart(DrawLibItem -> ChipName)) == NULL) {
  598.     sprintf(Line, "Failed to find part \"%s\" in library",
  599.                         DrawLibItem -> PartName);
  600.     IntrQueryContinue(Line, EEPopUpFrameColor,
  601.               EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
  602.               EEWindowsFrameWidth, &Cursor,
  603.               INTR_WNDW_PLACE_CENTER);
  604.     return NULL;
  605.     }
  606.  
  607.     IsMulti = Entry -> NumOfUnits > 0;
  608.     if (IsMulti) {
  609.     /* Make NextMulti point on next pin number in multi array: */
  610.     NextPinMulti = &Entry -> Multi[Entry -> PinsPerUnit * --Multi];
  611.  
  612.     NextPinText = NULL;
  613.     }
  614.     else {
  615.     NextPinNum = 1;
  616.     NextPinMulti = NULL;
  617.  
  618.     /* Make a copy of all pin text info so we can use strtok routine on: */
  619.     strncpy(Line, Entry -> Pins, LINE_LEN - 1);
  620.     NextPinText = strtok(Line, PIN_SEPERATOR);
  621.     }
  622.  
  623.     if (Entry -> Drawings != NULL) {
  624.     DEntry = Entry -> Drawings;
  625.     while (DEntry != NULL) {
  626.         switch (DEntry -> DrawType) {
  627.         case LINE_DRAW_TYPE:
  628.             x1 = PartX + TransMat[0][0] * DEntry -> U.Line.x1
  629.                    + TransMat[0][1] * DEntry -> U.Line.y1;
  630.             y1 = PartY + TransMat[1][0] * DEntry -> U.Line.x1
  631.                    + TransMat[1][1] * DEntry -> U.Line.y1;
  632.             x2 = PartX + TransMat[0][0] * DEntry -> U.Line.x2
  633.                    + TransMat[0][1] * DEntry -> U.Line.y2;
  634.             y2 = PartY + TransMat[1][0] * DEntry -> U.Line.x2
  635.                    + TransMat[1][1] * DEntry -> U.Line.y2;
  636.             if (IsMulti) {
  637.             p = LookUpPinText(Entry -> Pins, j = *NextPinMulti);
  638.             NextPinMulti++;
  639.             }
  640.             else {
  641.             p = NextPinText;
  642.             NextPinText = strtok(NULL, PIN_SEPERATOR);
  643.             j = NextPinNum++;
  644.             }
  645.  
  646.             if (LinesIntersect(lx1, ly1, lx2, ly2, x1, y1, x2, y2,
  647.                                l1Bus, FALSE, Phead))
  648.             PushNetListItem(&NetList, x1, y1, x2, y2,
  649.                     DrawLibItem -> PartName,
  650.                     DrawLibItem -> ChipName, p, j);
  651.             break;
  652.         }
  653.         DEntry = DEntry -> Pnext;
  654.     }
  655.     }
  656.     else {                      /* Simple a box with all pins: */
  657.     PinWidth = Entry -> TextInside ? PIN_WIDTH / 2 : PIN_WIDTH;
  658.     y1 = Entry -> TextInside ? PIN_WIDTH * Entry -> NumOfPins / 4 :
  659.                    PIN_WIDTH * Entry -> NumOfPins / 2;
  660.     x1 = Entry -> TextInside ? (int) (y1 * CHIP_BOX_ASPECT_TI) :
  661.                    (int) (y1 * CHIP_BOX_ASPECT_TO);
  662.     /* But make sure we can still print somethings inside... */
  663.     if (x1 < DRAW_TEXT_WIDTH * 12) x1 = DRAW_TEXT_WIDTH * 12;
  664.     x2 = x1 / 2;
  665.     y2 = y1 / 2;
  666.     x1 = -x2;
  667.     y1 = -y2;
  668.  
  669.     for (i = 0; i < Entry -> NumOfPins / 2; i++) {
  670.         y = y2 - PinWidth / 2 - i * PinWidth;
  671.         MapX1 = PartX + TransMat[0][0] * x1 + TransMat[0][1] * y;
  672.         MapY1 = PartY + TransMat[1][0] * x1 + TransMat[1][1] * y;
  673.         MapX2 = PartX + TransMat[0][0] * (x1 - PIN_LENGTH) + TransMat[0][1] * y;
  674.         MapY2 = PartY + TransMat[1][0] * (x1 - PIN_LENGTH) + TransMat[1][1] * y;
  675.         if (IsMulti) {
  676.         p = LookUpPinText(Entry -> Pins, j = *NextPinMulti);
  677.         NextPinMulti++;
  678.         }
  679.         else {
  680.         p = NextPinText;
  681.         NextPinText = strtok(NULL, PIN_SEPERATOR);
  682.         j = NextPinNum++;
  683.         }
  684.  
  685.         if (LinesIntersect(lx1, ly1, lx2, ly2,
  686.                    MapX1, MapY1, MapX2, MapY2,
  687.                    l1Bus, FALSE, Phead))
  688.         PushNetListItem(&NetList, MapX1, MapY1, MapX2, MapY2,
  689.                 DrawLibItem -> PartName,
  690.                 DrawLibItem -> ChipName, p, j);
  691.     }
  692.     for (i = Entry -> NumOfPins / 2 + 1; i <= Entry -> NumOfPins; i++) {
  693.         y = y1 + PinWidth / 2 + (i - Entry -> NumOfPins / 2 - 1) *
  694.                                 PinWidth;
  695.         MapX1 = PartX + TransMat[0][0] * x2 + TransMat[0][1] * y;
  696.         MapY1 = PartY + TransMat[1][0] * x2 + TransMat[1][1] * y;
  697.         MapX2 = PartX + TransMat[0][0] * (x2 + PIN_LENGTH) + TransMat[0][1] * y;
  698.         MapY2 = PartY + TransMat[1][0] * (x2 + PIN_LENGTH) + TransMat[1][1] * y;
  699.         if (IsMulti) {
  700.         p = LookUpPinText(Entry -> Pins, *NextPinMulti);
  701.         NextPinMulti++;
  702.         }
  703.         else {
  704.         p = NextPinText;
  705.         NextPinText = strtok(NULL, PIN_SEPERATOR);
  706.         NextPinNum++;
  707.         }
  708.         if (LinesIntersect(lx1, ly1, lx2, ly2,
  709.                    MapX1, MapY1, MapX2, MapY2,
  710.                    l1Bus, FALSE, Phead))
  711.         PushNetListItem(&NetList, MapX1, MapY1, MapX2, MapY2,
  712.                 DrawLibItem -> PartName,
  713.                 DrawLibItem -> ChipName, p, j);
  714.     }
  715.     }
  716.  
  717.     return NetList;
  718. }
  719.  
  720. /*****************************************************************************
  721. * Routine to push one net list item on the NetList list.             *
  722. * In addition the library item L line is drawn in current color/mode.        *
  723. *****************************************************************************/
  724. static void PushNetListItem(NetListStruct **NetList,
  725.                 int MapX1, int MapY1, int MapX2, int MapY2,
  726.                 char *PartName, char *ChipName, char *PinName,
  727.                 int PinNum)
  728. {
  729.     struct NetListStruct *NetListItem = (NetListStruct *)
  730.                           MyMalloc(sizeof(NetListStruct));
  731.  
  732.     if (ChipName == NULL) ChipName = "";
  733.     if (PartName == NULL) PartName = "";
  734.     if (PinName == NULL) PinName = "";
  735.  
  736.     if (ChipName[0] == '~') ChipName = &ChipName[1];
  737.     if (PartName[0] == '~') PartName = &PartName[1];
  738.     if (PinName[0] == '~') PinName = &PinName[1];
  739.  
  740.     sprintf(NetListItem -> Pin, "%s %s %s (Pin %d)",
  741.         ChipName, PartName, PinName, PinNum);
  742.  
  743.     NetListItem -> Pnext = *NetList;
  744.     *NetList = NetListItem;
  745.  
  746.     GRMoveTo(MapX1, MapY1);
  747.     GRLineTo(MapX2, MapY2);
  748. }
  749.  
  750. /*****************************************************************************
  751. * Routine to test if the given library item has non empty intersection with  *
  752. * the given box defined by x1/y1 and x2/y2 (x1 < x2, y1 < y2) and return     *
  753. * TRUE if so. Used to pick objects in a given box.                 *
  754. *****************************************************************************/
  755. BooleanType LibItemInBox(int x1, int y1, int x2, int y2,
  756.                         DrawLibItemStruct *DrawLibItem)
  757. {
  758.     int i, TempX, TempY, TempY1, TransMat[2][2], PartX, PartY, *Points,
  759.     xt1, yt1, xt2, yt2, PinWidth;
  760.     char Line[LINE_LEN_SHORT];
  761.     LibraryEntryStruct *Entry;
  762.     LibraryDrawEntryStruct *DEntry;
  763.  
  764.     GEN_COPY(TransMat, DrawLibItem -> Transform, sizeof(int) * 4);
  765.     PartX = DrawLibItem -> PosX;
  766.     PartY = DrawLibItem -> PosY;
  767.  
  768.     Cursor.CursorType = INTR_CURSOR_ARROW;
  769.  
  770.     if ((Entry = FindLibPart(DrawLibItem -> ChipName)) == NULL) {
  771.     sprintf(Line, "Failed to find part \"%s\" in library",
  772.                         DrawLibItem -> PartName);
  773.     IntrQueryContinue(Line, EEPopUpFrameColor,
  774.                   EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
  775.                           EEWindowsFrameWidth, &Cursor,
  776.                           INTR_WNDW_PLACE_CENTER);
  777.     return FALSE;
  778.     }
  779.  
  780.     if (Entry -> Drawings != NULL) {
  781.     DEntry = Entry -> Drawings;
  782.     while (DEntry != NULL) {
  783.         switch (DEntry -> DrawType) {
  784.         case LINE_DRAW_TYPE:
  785.             TempX = PartX + TransMat[0][0] * DEntry -> U.Line.x1
  786.                     + TransMat[0][1] * DEntry -> U.Line.y1;
  787.             TempY = PartY + TransMat[1][0] * DEntry -> U.Line.x1
  788.                     + TransMat[1][1] * DEntry -> U.Line.y1;
  789.             if (TempX >= x1 && TempX <= x2 &&
  790.             TempY >= y1 && TempY <= y2) return TRUE;
  791.  
  792.             TempX = PartX + TransMat[0][0] * DEntry -> U.Line.x2
  793.                     + TransMat[0][1] * DEntry -> U.Line.y2;
  794.             TempY = PartY + TransMat[1][0] * DEntry -> U.Line.x2
  795.                     + TransMat[1][1] * DEntry -> U.Line.y2;
  796.             if (TempX >= x1 && TempX <= x2 &&
  797.             TempY >= y1 && TempY <= y2) return TRUE;
  798.             break;
  799.         case SQUARE_DRAW_TYPE:
  800.             TempX = PartX + TransMat[0][0] * DEntry -> U.Sqr.x1
  801.                     + TransMat[0][1] * DEntry -> U.Sqr.y1;
  802.             TempY = PartY + TransMat[1][0] * DEntry -> U.Sqr.x1
  803.                     + TransMat[1][1] * DEntry -> U.Sqr.y1;
  804.             if (TempX >= x1 && TempX <= x2 &&
  805.             TempY >= y1 && TempY <= y2) return TRUE;
  806.  
  807.             TempX = PartX + TransMat[0][0] * DEntry -> U.Sqr.x2
  808.                     + TransMat[0][1] * DEntry -> U.Sqr.y2;
  809.             TempY = PartY + TransMat[1][0] * DEntry -> U.Sqr.x2
  810.                     + TransMat[1][1] * DEntry -> U.Sqr.y2;
  811.             if (TempX >= x1 && TempX <= x2 &&
  812.             TempY >= y1 && TempY <= y2) return TRUE;
  813.  
  814.             TempX = PartX + TransMat[0][0] * DEntry -> U.Sqr.x2
  815.                     + TransMat[0][1] * DEntry -> U.Sqr.y1;
  816.             TempY = PartY + TransMat[1][0] * DEntry -> U.Sqr.x2
  817.                     + TransMat[1][1] * DEntry -> U.Sqr.y1;
  818.             if (TempX >= x1 && TempX <= x2 &&
  819.             TempY >= y1 && TempY <= y2) return TRUE;
  820.  
  821.             TempX = PartX + TransMat[0][0] * DEntry -> U.Sqr.x1
  822.                     + TransMat[0][1] * DEntry -> U.Sqr.y2;
  823.             TempY = PartY + TransMat[1][0] * DEntry -> U.Sqr.x1
  824.                     + TransMat[1][1] * DEntry -> U.Sqr.y2;
  825.             if (TempX >= x1 && TempX <= x2 &&
  826.             TempY >= y1 && TempY <= y2) return TRUE;
  827.             break;
  828.         case POLYLINE_DRAW_TYPE:
  829.             Points = DEntry -> U.Poly.PolyList;
  830.             for (i = 0; i < DEntry -> U.Poly.n; i++) {
  831.             TempX = PartX + TransMat[0][0] * Points[i * 2]
  832.                       + TransMat[0][1] * Points[i * 2 + 1];
  833.             TempY = PartY + TransMat[1][0] * Points[i * 2]
  834.                       + TransMat[1][1] * Points[i * 2 + 1];
  835.             if (TempX >= x1 && TempX <= x2 &&
  836.                 TempY >= y1 && TempY <= y2) return TRUE;
  837.  
  838.             }
  839.             break;
  840.         case ARC_DRAW_TYPE:
  841.         case CIRCLE_DRAW_TYPE:
  842.         case TEXT_DRAW_TYPE:
  843.             break;
  844.         }
  845.         DEntry = DEntry -> Pnext;
  846.     }
  847.     }
  848.     else {                      /* Simple a box with all pins: */
  849.     yt1 = Entry -> TextInside ? PIN_WIDTH * Entry -> NumOfPins / 4 :
  850.                     PIN_WIDTH * Entry -> NumOfPins / 2;
  851.     xt1 = Entry -> TextInside ? (int) (yt1 * CHIP_BOX_ASPECT_TI) :
  852.                     (int) (yt1 * CHIP_BOX_ASPECT_TO);
  853.         /* But make sure we can still print somethings inside... */
  854.     if (xt1 < DRAW_TEXT_WIDTH * 12) xt1 = DRAW_TEXT_WIDTH * 12;
  855.     xt2 = xt1 / 2;
  856.     yt2 = yt1 / 2;
  857.     xt1 = -xt2;
  858.     yt1 = -yt2;
  859.     PinWidth = Entry -> TextInside ? PIN_WIDTH / 2 : PIN_WIDTH;
  860.  
  861.     for (i = 0; i < Entry -> NumOfPins / 2; i++) {
  862.         TempY1 = yt2 - PinWidth / 2 - i * PinWidth;
  863.         TempX = PartX + TransMat[0][0] * (xt1 - PIN_LENGTH) +
  864.                 TransMat[0][1] * TempY1;
  865.         TempY = PartY + TransMat[1][0] * (xt1 - PIN_LENGTH) +
  866.                 TransMat[1][1] * TempY1;
  867.         if (TempX >= x1 && TempX <= x2 &&
  868.         TempY >= y1 && TempY <= y2) return TRUE;
  869.     }
  870.     for (i = Entry -> NumOfPins / 2 + 1; i <= Entry -> NumOfPins; i++) {
  871.         TempY1 = yt1 + PinWidth / 2 + (i - Entry -> NumOfPins / 2 - 1) *
  872.                                 PinWidth;
  873.         TempX = PartX + TransMat[0][0] * (xt2 + PIN_LENGTH) +
  874.                 TransMat[0][1] * TempY1;
  875.         TempY = PartY + TransMat[1][0] * (xt2 + PIN_LENGTH) +
  876.                 TransMat[1][1] * TempY1;
  877.         if (TempX >= x1 && TempX <= x2 &&
  878.         TempY >= y1 && TempY <= y2) return TRUE;
  879.     }
  880.     }
  881.  
  882.     return FALSE;
  883. }
  884.  
  885. /*****************************************************************************
  886. * Given the Pins string and PinNum returns NULL terminated string of that    *
  887. * pin allocated statically.                             *
  888. *****************************************************************************/
  889. static char *LookUpPinText(char *Pins, int PinNum)
  890. {
  891.     static char Pin[MAX_PIN_INFO];
  892.     int i,
  893.         Count = 1;
  894.  
  895.     while (*Pins && Count != PinNum) {
  896.     if (*Pins++ == PIN_SEPERATOR[0]) Count++;
  897.     }
  898.  
  899.     if (*Pins) {
  900.     i = 0;
  901.     while (i < MAX_PIN_INFO - 1 && *Pins != PIN_SEPERATOR[0] && *Pins != 0)
  902.         Pin[i++] = *Pins++;
  903.     Pin[i] = 0;
  904.     return i > 0 ? Pin : NULL;
  905.     }
  906.     else {
  907.     return NULL;
  908.     }
  909. }
  910.  
  911. /*****************************************************************************
  912. * Routine to rotate the given angular direction by the given Transformation. *
  913. * Input (and output) angles must be as follows:                     *
  914. * Angle1 in [0..360], Angle2 > Angle1 in [0..720]. Arc is assumed to be less *
  915. * than 180 degrees.                                 *
  916. * Algorithm:                                     *
  917. * Map the angles to a point on the unit circle which is mapped using the     *
  918. * transform (only mirror and rotate so it remains on the unit circle) to     *
  919. * a new point which is used to detect new angle.                 *
  920. *****************************************************************************/
  921. static void MapAngles(int *Angle1, int *Angle2, int TransMat[2][2])
  922. {
  923.     int Angle;
  924.     RealType x, y, t;
  925.  
  926.     x = cos(*Angle1 * M_PI / 180.0);
  927.     y = sin(*Angle1 * M_PI / 180.0);
  928.     t = x * TransMat[0][0] + y * TransMat[0][1];
  929.     y = x * TransMat[1][0] + y * TransMat[1][1];
  930.     x = t;
  931.     *Angle1 = (int) (atan2(y, x) * 180.0 / M_PI + 0.5);
  932.  
  933.     x = cos(*Angle2 * M_PI / 180.0);
  934.     y = sin(*Angle2 * M_PI / 180.0);
  935.     t = x * TransMat[0][0] + y * TransMat[0][1];
  936.     y = x * TransMat[1][0] + y * TransMat[1][1];
  937.     x = t;
  938.     *Angle2 = (int) (atan2(y, x) * 180.0 / M_PI + 0.5);
  939.  
  940.     NORMALIZE_ANGLE(*Angle1);
  941.     NORMALIZE_ANGLE(*Angle2);
  942.     if (*Angle2 < *Angle1) *Angle2 += 360;
  943.  
  944.     if (*Angle2 - *Angle1 > 180) {         /* Need to swap the two angles. */
  945.     Angle = (*Angle1);
  946.     *Angle1 = (*Angle2);
  947.     *Angle2 = Angle;
  948.  
  949.     NORMALIZE_ANGLE(*Angle1);
  950.     NORMALIZE_ANGLE(*Angle2);
  951.     if (*Angle2 < *Angle1) *Angle2 += 360;
  952.     }
  953.  
  954.     *Angle1 -= 1;    /* As the angles loaded are decreased by 1 when loaded. */
  955.     *Angle2 += 1;
  956. }
  957.  
  958. /*****************************************************************************
  959. * Routine to view one selected library content.                     *
  960. *****************************************************************************/
  961. static void ViewOneLibrary(LibraryStruct *Lib)
  962. {
  963.     int i, x, y, TransMat[2][2],
  964.     NumOfParts = Lib -> NumOfParts;
  965.     char **PartNames;
  966.     LibraryEntryStruct *LibEntry, *Entry,
  967.     *LastEntry = NULL;
  968.  
  969.     Cursor.CursorType = INTR_CURSOR_ARROW;
  970.  
  971.     if (NumOfParts == 0) {
  972.     IntrQueryContinue("Library is empty!", EEPopUpFrameColor,
  973.                   EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
  974.                           EEWindowsFrameWidth, &Cursor,
  975.                           INTR_WNDW_PLACE_CENTER);
  976.     return;
  977.     }
  978.     PartNames = (char **) MyMalloc(sizeof(char *) * NumOfParts);
  979.  
  980.     PQCompFunc((PQCompFuncType) LibraryEntryCompare);
  981.     LibEntry = (LibraryEntryStruct *) PQFirst(&Lib -> Entries, FALSE);
  982.     PartNames[0] = LibEntry -> Name;
  983.     for (i = 1; i < NumOfParts; i++) {
  984.     if ((LibEntry = (LibraryEntryStruct *)
  985.           PQNext(Lib -> Entries, LibEntry, NULL)) == NULL) {
  986.         /* Number of parts does not match what we really have. This is   */
  987.         /* wierd but we will try to do what we can:                 */
  988.         NumOfParts = i - 1;
  989.         break;
  990.     }
  991.     PartNames[i] = LibEntry -> Name;
  992.     }
  993.  
  994.     x = GRInvMapX(GRScreenMaxX * 3 / 4);     /* Where to put the drawn part: */
  995.     y = GRInvMapY(GRScreenMaxY / 2);
  996.     TransMat[0][0] = 1.0;
  997.     TransMat[1][1] = -1.0;
  998.     TransMat[1][0] = TransMat[0][1] = 0.0;
  999.  
  1000.     do {
  1001.     i = IntrQueryList("ViewLib", (char **) PartNames, 0, NumOfParts,
  1002.               EEListNumDisplayed, EEPopUpFrameColor,
  1003.                           EEPopUpBackColor, EEPopUpForeColor,
  1004.                           EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  1005.                           INTR_WNDW_PLACE_LEFT);
  1006.  
  1007.     if (LastEntry) {                  /* Erase old part. */
  1008.         DrawLibPartAux(LastEntry, x, y, TransMat, 1, GR_COPY_PUT,
  1009.                           IntrAllocColor(EERootWndwBackColor,
  1010.                                  INTR_INTENSITY_HIGH));
  1011.         LastEntry = NULL;
  1012.     }
  1013.  
  1014.     if (i >= 0) {                       /* Draw new part. */
  1015.         Entry = FindLibPart(PartNames[i]);
  1016.         DrawLibPartAux(Entry, x, y, TransMat,
  1017.                                1, GR_COPY_PUT, EE_DRAW_COLOR);
  1018.         LastEntry = Entry;
  1019.     }
  1020.     }
  1021.     while (i >= 0);
  1022.  
  1023.     MyFree((VoidPtr) PartNames);
  1024. }
  1025.  
  1026. /*****************************************************************************
  1027. * Routine to handle lib part creation. Return NULL if fails.             *
  1028. *****************************************************************************/
  1029. DrawGenericStruct *LibCreateNewPart(void)
  1030. {
  1031.     static char Name[LINE_LEN_SHORT] = { 0 };
  1032.     int x, y, TransMat[2][2], TempMat[2][2], TempR, Multi, PopPosition;
  1033.     BooleanType Transform,
  1034.     Quit = FALSE;
  1035.     char Line[LINE_LEN], Buffer[LINE_LEN_SHORT];
  1036.     LibraryEntryStruct *Entry;
  1037.     DrawLibItemStruct *DrawLibItem;
  1038.  
  1039.     IntrQueryLine("Library part name:", Name, LINE_LEN_SHORT - 1,
  1040.               EEPopUpFrameColor, EEPopUpBackColor, EEPopUpForeColor,
  1041.                   EEWindowsFrameWidth, INTR_WNDW_PLACE_CENTER);
  1042.  
  1043.     if (strlen(Name) == 0) return NULL;
  1044.     strupr(Name);
  1045.  
  1046.     Cursor.CursorType = INTR_CURSOR_ARROW;
  1047.  
  1048.     if ((Entry = FindLibPart(Name)) == NULL) {
  1049.     sprintf(Line, "Failed to find part \"%s\" in library", Name);
  1050.     IntrQueryContinue(Line, EEPopUpFrameColor,
  1051.                   EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
  1052.                           EEWindowsFrameWidth, &Cursor, INTR_WNDW_PLACE_CENTER);
  1053.     return NULL;
  1054.     }
  1055.  
  1056.     if (Entry -> NumOfUnits > 1) {
  1057.     do {
  1058.         sprintf(Line, "This chip has %d multiple units. Which one (1-%d):",
  1059.                 Entry -> NumOfUnits, Entry -> NumOfUnits);
  1060.         strcpy(Buffer, "1");
  1061.         IntrQueryLine(Line, Buffer, LINE_LEN_SHORT - 1,
  1062.                       EEPopUpFrameColor, EEPopUpBackColor,
  1063.                           EEPopUpForeColor, EEWindowsFrameWidth,
  1064.                           INTR_WNDW_PLACE_CENTER);
  1065.     }
  1066.     while (sscanf(Buffer, "%d", &Multi) != 1 ||
  1067.            Multi <= 0 ||
  1068.            Multi > Entry -> NumOfUnits);
  1069.     }
  1070.     else
  1071.     Multi = 1;
  1072.  
  1073.     x = GRScreenMaxX * 3 / 4;             /* Where to put the drawn part: */
  1074.     y = GRScreenMaxY / 2;
  1075.  
  1076.     /* Prepare the transformation information: */
  1077.     TransMat[0][0] = 1.0;
  1078.     TransMat[1][1] = -1.0;
  1079.     TransMat[1][0] = TransMat[0][1] = 0.0;
  1080.  
  1081.     if (TransPopUpMenu == NULL) TransPopUpMenu =
  1082.         IntrPopUpMenuCreate("Transform", (char **) TransformStrs, 0,
  1083.                     TRANS_MENU_SIZE, EEPopUpFrameColor,
  1084.                             EEPopUpBackColor, EEPopUpForeColor,
  1085.                             EEPopUpXorColor, EEWindowsFrameWidth, &Cursor);
  1086.  
  1087.     do {
  1088.     DrawLibPartAux(Entry, GRInvMapX(x), GRInvMapY(y), TransMat,
  1089.                Multi, GR_COPY_PUT, EE_HIGHLIGHT_COLOR);
  1090.  
  1091.     if (!IntrPopUpMenu(TransPopUpMenu, INTR_WNDW_PLACE_LEFT)) {
  1092.             /* If abort key. */
  1093.         DrawLibPartAux(Entry, GRInvMapX(x), GRInvMapY(y), TransMat,
  1094.                    Multi, GR_COPY_PUT, EE_ERASE_COLOR);
  1095.         return NULL;
  1096.     }
  1097.  
  1098.     DrawLibPartAux(Entry, GRInvMapX(x), GRInvMapY(y), TransMat,
  1099.                Multi, GR_COPY_PUT, EE_ERASE_COLOR);
  1100.  
  1101.     Transform = TRUE;
  1102.     if (!Quit) switch (TransPopUpMenu -> SelectedIndex) {
  1103.         case 0:
  1104.         Quit = TRUE;
  1105.         break;
  1106.         case 2:
  1107.         TempMat[0][0] = TempMat[1][1] = 0.0;
  1108.         TempMat[0][1] = 1.0;
  1109.         TempMat[1][0] = -1.0;
  1110.         break;
  1111.         case 3:
  1112.         TempMat[0][0] = TempMat[1][1] = 0.0;
  1113.         TempMat[0][1] = -1.0;
  1114.         TempMat[1][0] = 1.0;
  1115.         break;
  1116.         case 4:
  1117.         TempMat[0][0] = -1.0;
  1118.         TempMat[1][1] = 1.0;
  1119.         TempMat[0][1] = TempMat[1][0] = 0.0;
  1120.         break;
  1121.         case 5:
  1122.         TempMat[0][0] = 1.0;
  1123.         TempMat[1][1] = -1.0;
  1124.         TempMat[0][1] = TempMat[1][0] = 0.0;
  1125.         break;
  1126.         default:
  1127.         Transform = FALSE;
  1128.         break;
  1129.     }
  1130.     if (!Quit && Transform) {
  1131.         TempR = TransMat[0][0] * TempMat[0][0] +
  1132.                         TransMat[0][1] * TempMat[1][0];
  1133.         TransMat[0][1] = TransMat[0][0] * TempMat[0][1] +
  1134.                         TransMat[0][1] * TempMat[1][1];
  1135.         TransMat[0][0] = TempR;
  1136.         TempR = TransMat[1][0] * TempMat[0][0] +
  1137.                         TransMat[1][1] * TempMat[1][0];
  1138.         TransMat[1][1] = TransMat[1][0] * TempMat[0][1] +
  1139.                         TransMat[1][1] * TempMat[1][1];
  1140.         TransMat[1][0] = TempR;
  1141.     }
  1142.     }
  1143.     while (!Quit);
  1144.  
  1145.     /* Allocate the structure to be returned, and fill it with information   */
  1146.     /* we know so far.                                 */
  1147.     DrawLibItem = (DrawLibItemStruct *) MyMalloc(sizeof(DrawLibItemStruct));
  1148.     DrawLibItem -> Pnext = NULL;
  1149.     DrawLibItem -> StructType = DRAW_LIB_ITEM_STRUCT_TYPE;
  1150.     DrawLibItem -> Multi = Multi;
  1151.     DrawLibItem -> PartNameOrient =
  1152.     DrawLibItem -> ChipNameOrient = TEXT_ORIENT_NON;
  1153.     DrawLibItem -> ChipName = strdup(Name);
  1154.     DrawLibItem -> PartName = NULL;
  1155.     DrawLibItem -> PosX = DrawLibItem -> PosY = -20000;
  1156.     GEN_COPY(DrawLibItem -> Transform, TransMat, sizeof(int) * 4);
  1157.  
  1158.     PutCursorInActiveWindow();
  1159.     IntrSetIdleFunction(AutoPanActiveWindow);
  1160.  
  1161.     /* Place the part in its exact place and update part and chip names. */
  1162.     if (!PlaceLibItem(DrawLibItem)) {
  1163.     MyFree((VoidPtr) DrawLibItem);
  1164.         IntrSetIdleFunction(NULL);
  1165.     return NULL;
  1166.     }
  1167.  
  1168.     IntrSetIdleFunction(NULL);
  1169.  
  1170.     /* Update the BBox knowledge: */
  1171.     DrawLibItem -> BBoxMinX = DrawLibItem -> PosX + Entry -> BBoxMinX;
  1172.     DrawLibItem -> BBoxMaxX = DrawLibItem -> PosX + Entry -> BBoxMaxX;
  1173.     DrawLibItem -> BBoxMinY = DrawLibItem -> PosY + Entry -> BBoxMinY;
  1174.     DrawLibItem -> BBoxMaxY = DrawLibItem -> PosY + Entry -> BBoxMaxY;
  1175.  
  1176.     DrawLibPart(DrawLibItem, GR_COPY_PUT, EE_HIGHLIGHT_COLOR);
  1177.  
  1178.     /* Put the structure in the global object list, so automatic panning     */
  1179.     /* will draw it as well. It will be removed from EEDrawList before exit. */
  1180.     DrawLibItem -> Pnext = EEActiveWindow -> EEDrawList;
  1181.     EEActiveWindow -> EEDrawList = (DrawGenericStruct *) DrawLibItem;
  1182.  
  1183.     PopPosition = GRMapX(DrawLibItem -> PosX) < GRScreenMaxX / 2 ?
  1184.                             INTR_WNDW_PLACE_RIGHT :
  1185.                             INTR_WNDW_PLACE_LEFT;
  1186.  
  1187.     Cursor.CursorType = INTR_CURSOR_ARROW;
  1188.  
  1189.     if (Entry -> DrawName &&
  1190.     IntrQueryYesNo("Display chip name?", EEPopUpFrameColor,
  1191.                EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
  1192.                        EEWindowsFrameWidth, &Cursor, PopPosition)) {
  1193.     DrawLibItem -> ChipNameX = DrawLibItem -> PosX;
  1194.     DrawLibItem -> ChipNameY = DrawLibItem -> PosY;
  1195.     if (!PlaceString(DrawLibItem -> ChipName,
  1196.              &DrawLibItem -> ChipNameOrient,
  1197.              1,
  1198.              &DrawLibItem -> ChipNameX,
  1199.              &DrawLibItem -> ChipNameY,
  1200.                          PopPosition)) {
  1201.         EEActiveWindow -> EEDrawList =       /* Remove from global list. */
  1202.                 EEActiveWindow -> EEDrawList -> Pnext;
  1203.         DrawLibPart(DrawLibItem, GR_COPY_PUT, EE_ERASE_COLOR);
  1204.         MyFree((VoidPtr) DrawLibItem -> ChipName);
  1205.         MyFree((VoidPtr) DrawLibItem);
  1206.         return NULL;
  1207.     }
  1208.     }
  1209.  
  1210.     DrawLibPart(DrawLibItem, GR_COPY_PUT, EE_HIGHLIGHT_COLOR);
  1211.  
  1212.     strcpy(Line, Entry -> Prefix);
  1213.  
  1214.     Cursor.CursorType = INTR_CURSOR_ARROW;
  1215.  
  1216.     if (strlen(Entry -> Prefix) > 0 &&
  1217.     IntrQueryYesNo("Display part name?", EEPopUpFrameColor,
  1218.                        EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
  1219.                        EEWindowsFrameWidth, &Cursor, PopPosition) &&
  1220.     strlen(IntrQueryLine("Part name:", Line, LINE_LEN - 1,
  1221.                      EEPopUpFrameColor, EEPopUpBackColor,
  1222.                              EEPopUpForeColor, EEWindowsFrameWidth,
  1223.                              PopPosition)) > 0) {
  1224.     DrawLibItem -> PartName = strdup(Line);
  1225.     DrawLibItem -> PartNameX = DrawLibItem -> PosX;
  1226.     DrawLibItem -> PartNameY = DrawLibItem -> PosY;
  1227.     if (!PlaceString(DrawLibItem -> PartName,
  1228.              &DrawLibItem -> PartNameOrient,
  1229.              1,
  1230.              &DrawLibItem -> PartNameX,
  1231.              &DrawLibItem -> PartNameY,
  1232.                          PopPosition)) {
  1233.         if (DrawLibItem -> ChipName)
  1234.         MyFree((VoidPtr) DrawLibItem -> ChipName);
  1235.         EEActiveWindow -> EEDrawList =     /* Remove from global list. */
  1236.                 EEActiveWindow -> EEDrawList -> Pnext;
  1237.         DrawLibPart(DrawLibItem, GR_COPY_PUT, EE_ERASE_COLOR);
  1238.         MyFree((VoidPtr) DrawLibItem -> PartName);
  1239.         MyFree((VoidPtr) DrawLibItem);
  1240.         return NULL;
  1241.     }
  1242.     }
  1243.  
  1244.     DrawLibPart(DrawLibItem, GR_COPY_PUT, EE_DRAW_COLOR);
  1245.  
  1246.     EEActiveWindow -> EEDrawList =
  1247.         EEActiveWindow -> EEDrawList -> Pnext;   /* Remove from global list. */
  1248.     DrawLibItem -> Pnext = NULL;
  1249.  
  1250.     return (DrawGenericStruct *) DrawLibItem;
  1251. }
  1252.  
  1253. /*****************************************************************************
  1254. * Routine to reposition a library item.                         *
  1255. *****************************************************************************/
  1256. BooleanType RePosLibItem(DrawLibItemStruct *DrawLibItem, int PopPosition)
  1257. {
  1258.     BooleanType Transform,
  1259.     RetVal = FALSE;
  1260.     int TempR, *TransMat[2], TempMat[2][2];
  1261.  
  1262.     /* Prepare the transformation information: */
  1263.     TransMat[0] = DrawLibItem -> Transform[0];
  1264.     TransMat[1] = DrawLibItem -> Transform[1];
  1265.  
  1266.     Cursor.CursorType = INTR_CURSOR_ARROW;
  1267.  
  1268.     if (TransPopUpMenu == NULL) TransPopUpMenu =
  1269.         IntrPopUpMenuCreate("Transform", (char **) TransformStrs, 0,
  1270.                     TRANS_MENU_SIZE, EEPopUpFrameColor,
  1271.                             EEPopUpBackColor, EEPopUpForeColor,
  1272.                             EEPopUpXorColor, EEWindowsFrameWidth, &Cursor);
  1273.  
  1274.     while (TRUE) {
  1275.     if (!IntrPopUpMenu(TransPopUpMenu, PopPosition))
  1276.         return RetVal;
  1277.  
  1278.         Transform = TRUE;
  1279.     switch (TransPopUpMenu -> SelectedIndex) {
  1280.         case 0:
  1281.         return RetVal;
  1282.         case 2:
  1283.         TempMat[0][0] = TempMat[1][1] = 0.0;
  1284.         TempMat[0][1] = 1.0;
  1285.         TempMat[1][0] = -1.0;
  1286.         break;
  1287.         case 3:
  1288.         TempMat[0][0] = TempMat[1][1] = 0.0;
  1289.         TempMat[0][1] = -1.0;
  1290.         TempMat[1][0] = 1.0;
  1291.         break;
  1292.         case 4:
  1293.         TempMat[0][0] = 1.0;
  1294.         TempMat[1][1] = -1.0;
  1295.         TempMat[0][1] = TempMat[1][0] = 0.0;
  1296.         break;
  1297.         case 5:
  1298.         TempMat[0][0] = -1.0;
  1299.         TempMat[1][1] = 1.0;
  1300.         TempMat[0][1] = TempMat[1][0] = 0.0;
  1301.         break;
  1302.         default:
  1303.         Transform = FALSE;
  1304.         break;
  1305.     }
  1306.     if (Transform) {
  1307.         DrawLibPart(DrawLibItem, GR_COPY_PUT, EE_ERASE_COLOR);
  1308.  
  1309.         TempR = TransMat[0][0] * TempMat[0][0] +
  1310.                         TransMat[0][1] * TempMat[1][0];
  1311.         TransMat[0][1] = TransMat[0][0] * TempMat[0][1] +
  1312.                         TransMat[0][1] * TempMat[1][1];
  1313.         TransMat[0][0] = TempR;
  1314.         TempR = TransMat[1][0] * TempMat[0][0] +
  1315.                         TransMat[1][1] * TempMat[1][0];
  1316.         TransMat[1][1] = TransMat[1][0] * TempMat[0][1] +
  1317.                         TransMat[1][1] * TempMat[1][1];
  1318.         TransMat[1][0] = TempR;
  1319.  
  1320.         DrawLibPart(DrawLibItem, GR_COPY_PUT, EE_HIGHLIGHT_COLOR);
  1321.  
  1322.             RetVal = TRUE;
  1323.     }
  1324.     }
  1325. }
  1326.  
  1327. /*****************************************************************************
  1328. * Routine to place a library item. Return FALSE if ABORT signaled.         *
  1329. *****************************************************************************/
  1330. BooleanType PlaceLibItem(DrawLibItemStruct *DrawLibItem)
  1331. {
  1332.     int Event, NewPosX, NewPosY, OldPosX, OldPosY, Dx, Dy;
  1333.     char Line[LINE_LEN_SHORT];
  1334.     LibraryEntryStruct *Entry;
  1335.  
  1336.     Cursor.CursorType = INTR_CURSOR_ARROW;
  1337.  
  1338.     if ((Entry = FindLibPart(DrawLibItem -> ChipName)) == NULL) {
  1339.     sprintf(Line, "Failed to find part \"%s\" in library",
  1340.                         DrawLibItem -> ChipName);
  1341.     IntrQueryContinue(Line, EEPopUpFrameColor,
  1342.                   EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
  1343.                           EEWindowsFrameWidth, &Cursor, INTR_WNDW_PLACE_CENTER);
  1344.     return FALSE;
  1345.     }
  1346.     IntrPushCursorType();
  1347.     Cursor.CursorType = INTR_CURSOR_CUSTOM;
  1348.     Cursor.CursorRoutine = DrawingEntryCursor;
  1349.     IntrSetCursorType(&Cursor);
  1350.  
  1351.     CrsrDrawLibItem = DrawLibItem;
  1352.     CrsrLibEntry = Entry;
  1353.     if (DrawLibItem -> PosX == -20000) {        /* First time placement. */
  1354.     DrawLibItem -> PosX = EE_SNAP(GRInvMapX((EEActiveBBox -> Xmin +
  1355.                          EEActiveBBox -> Xmax) / 2));
  1356.     DrawLibItem -> PosY = EE_SNAP(GRInvMapY((EEActiveBBox -> Ymin +
  1357.                          EEActiveBBox -> Ymax) / 2));
  1358.     }
  1359.     GRCurrentCursorX = GRMapX(DrawLibItem -> PosX);
  1360.     GRCurrentCursorY = GRMapY(DrawLibItem -> PosY);
  1361.     sprintf(Line, "Place part \"%s\"", DrawLibItem -> ChipName);
  1362.     IntrDrawMessage(Line, EEPopUpForeColor, EEPopUpBackColor);
  1363.  
  1364.     OldPosX = DrawLibItem -> PosX;
  1365.     OldPosY = DrawLibItem -> PosY;
  1366.  
  1367.     if ((Event = IntrGetEventWaitSA(&NewPosX, &NewPosY)) == INTR_EVNT_SELECT) {
  1368.         DrawLibItem -> PosX = GRInvMapX(NewPosX);
  1369.     DrawLibItem -> PosY = GRInvMapY(NewPosY);
  1370.     DrawLibItem -> PosX = EE_SNAP(DrawLibItem -> PosX);
  1371.     DrawLibItem -> PosY = EE_SNAP(DrawLibItem -> PosY);
  1372.     Dx = DrawLibItem -> PosX - OldPosX;
  1373.     Dy = DrawLibItem -> PosY - OldPosY;
  1374.     DrawLibItem -> PartNameX += Dx;
  1375.     DrawLibItem -> PartNameY += Dy;
  1376.     DrawLibItem -> ChipNameX += Dx;
  1377.     DrawLibItem -> ChipNameY += Dy;
  1378.     DrawLibItem -> BBoxMinX += Dx;
  1379.     DrawLibItem -> BBoxMinY += Dy;
  1380.     DrawLibItem -> BBoxMaxX += Dx;
  1381.     DrawLibItem -> BBoxMaxY += Dy;
  1382.     }
  1383.  
  1384.     IntrEraseMessage();
  1385.  
  1386.     IntrPopCursorType();
  1387.     Cursor.CursorType = INTR_CURSOR_ARROW;
  1388.  
  1389.     return Event != INTR_EVNT_ABORT;
  1390. }
  1391.  
  1392. /*****************************************************************************
  1393. * Routine to display an outline version of given library entry.             *
  1394. * This routine is applied by the LibCreateNewpart routine above.         *
  1395. *****************************************************************************/
  1396. static void DrawingEntryCursor(int PartX, int PartY)
  1397. {
  1398.     int i, x1, y1, x2, y2, PinWidth,
  1399.     y, MapX1, MapY1, MapX2, MapY2, TransMat[2][2],
  1400.         LastColor = GRGetColor();
  1401.     LibraryDrawEntryStruct *DEntry;
  1402.  
  1403.     /* Map from screen coords. to drawing coords. and offset as required. */
  1404.     GRSetColor(EE_HIGHLIGHT_COLOR);
  1405.  
  1406.     PartX = GRInvMapX(PartX);
  1407.     PartY = GRInvMapY(PartY);
  1408.  
  1409.     GEN_COPY(TransMat, CrsrDrawLibItem -> Transform, sizeof(int) * 4);
  1410.  
  1411.     if (CrsrLibEntry -> Drawings != NULL) {
  1412.     DEntry = CrsrLibEntry -> Drawings;
  1413.     while (DEntry != NULL) {
  1414.         switch (DEntry -> DrawType) {
  1415.         case ARC_DRAW_TYPE:
  1416.         case CIRCLE_DRAW_TYPE:
  1417.         case TEXT_DRAW_TYPE:
  1418.             break;
  1419.         case SQUARE_DRAW_TYPE:
  1420.             x1 = PartX + TransMat[0][0] * DEntry -> U.Sqr.x1
  1421.                    + TransMat[0][1] * DEntry -> U.Sqr.y1;
  1422.             y1 = PartY + TransMat[1][0] * DEntry -> U.Sqr.x1
  1423.                    + TransMat[1][1] * DEntry -> U.Sqr.y1;
  1424.             x2 = PartX + TransMat[0][0] * DEntry -> U.Sqr.x2
  1425.                    + TransMat[0][1] * DEntry -> U.Sqr.y2;
  1426.             y2 = PartY + TransMat[1][0] * DEntry -> U.Sqr.x2
  1427.                    + TransMat[1][1] * DEntry -> U.Sqr.y2;
  1428.             GRMoveTo(x1, y1);
  1429.             GRLineTo(x1, y2);
  1430.             GRLineTo(x2, y2);
  1431.             GRLineTo(x2, y1);
  1432.             GRLineTo(x1, y1);
  1433.             break;
  1434.         case LINE_DRAW_TYPE:
  1435.             GRMoveTo(x1 = PartX + TransMat[0][0] * DEntry -> U.Line.x1
  1436.                     + TransMat[0][1] * DEntry -> U.Line.y1,
  1437.                  y1 = PartY + TransMat[1][0] * DEntry -> U.Line.x1
  1438.                     + TransMat[1][1] * DEntry -> U.Line.y1);
  1439.             GRLineTo(x2 = PartX + TransMat[0][0] * DEntry -> U.Line.x2
  1440.                     + TransMat[0][1] * DEntry -> U.Line.y2,
  1441.                  y2 = PartY + TransMat[1][0] * DEntry -> U.Line.x2
  1442.                     + TransMat[1][1] * DEntry -> U.Line.y2);
  1443.             break;
  1444.         case POLYLINE_DRAW_TYPE:
  1445.             GRMoveTo(PartX +
  1446.             TransMat[0][0] * DEntry -> U.Poly.PolyList[0] +
  1447.             TransMat[0][1] * DEntry -> U.Poly.PolyList[1],
  1448.                  PartY +
  1449.             TransMat[1][0] * DEntry -> U.Poly.PolyList[0] +
  1450.             TransMat[1][1] * DEntry -> U.Poly.PolyList[1]);
  1451.             for (i = 1; i < DEntry -> U.Poly.n; i++)
  1452.             GRLineTo(PartX +
  1453.                 TransMat[0][0] * DEntry -> U.Poly.PolyList[i * 2] +
  1454.                 TransMat[0][1] * DEntry -> U.Poly.PolyList[i * 2 + 1],
  1455.                  PartY +
  1456.                 TransMat[1][0] * DEntry -> U.Poly.PolyList[i * 2] +
  1457.                 TransMat[1][1] * DEntry -> U.Poly.PolyList[i * 2 + 1]);
  1458.             break;
  1459.         }
  1460.         DEntry = DEntry -> Pnext;
  1461.     }
  1462.     }
  1463.     else {          /* NULL Drawing - draw simple a box with all pins: */
  1464.     y1 = CrsrLibEntry -> TextInside ?
  1465.         PIN_WIDTH * CrsrLibEntry -> NumOfPins / 4 :
  1466.         PIN_WIDTH * CrsrLibEntry -> NumOfPins / 2;
  1467.     x1 = CrsrLibEntry -> TextInside ? (int) (y1 * CHIP_BOX_ASPECT_TI) :
  1468.                       (int) (y1 * CHIP_BOX_ASPECT_TO);
  1469.         /* But make sure we can still print somethings inside... */
  1470.     if (x1 < DRAW_TEXT_WIDTH * 12) x1 = DRAW_TEXT_WIDTH * 12;
  1471.     x2 = x1 / 2;
  1472.     y2 = y1 / 2;
  1473.     x1 = -x2;
  1474.     y1 = -y2;
  1475.     PinWidth = CrsrLibEntry -> TextInside ? PIN_WIDTH / 2 : PIN_WIDTH;
  1476.  
  1477.     GRMoveTo(PartX + TransMat[0][0] * x1 + TransMat[0][1] * y1,
  1478.          PartY + TransMat[1][0] * x1 + TransMat[1][1] * y1);
  1479.     GRLineTo(PartX + TransMat[0][0] * x1 + TransMat[0][1] * y2,
  1480.          PartY + TransMat[1][0] * x1 + TransMat[1][1] * y2);
  1481.     GRLineTo(PartX + TransMat[0][0] * x2 + TransMat[0][1] * y2,
  1482.          PartY + TransMat[1][0] * x2 + TransMat[1][1] * y2);
  1483.     GRLineTo(PartX + TransMat[0][0] * x2 + TransMat[0][1] * y1,
  1484.          PartY + TransMat[1][0] * x2 + TransMat[1][1] * y1);
  1485.     GRLineTo(PartX + TransMat[0][0] * x1 + TransMat[0][1] * y1,
  1486.          PartY + TransMat[1][0] * x1 + TransMat[1][1] * y1);
  1487.     for (i = 0; i < CrsrLibEntry -> NumOfPins / 2; i++) {
  1488.         y = y2 - PinWidth / 2 - i * PinWidth;
  1489.         MapX1 = PartX + TransMat[0][0] * x1 + TransMat[0][1] * y;
  1490.         MapY1 = PartY + TransMat[1][0] * x1 + TransMat[1][1] * y;
  1491.         MapX2 = PartX + TransMat[0][0] * (x1 - PIN_LENGTH) + TransMat[0][1] * y;
  1492.         MapY2 = PartY + TransMat[1][0] * (x1 - PIN_LENGTH) + TransMat[1][1] * y;
  1493.         GRMoveTo(MapX1, MapY1);
  1494.         GRLineTo(MapX2, MapY2);
  1495.     }
  1496.     for (i = CrsrLibEntry -> NumOfPins / 2 + 1;
  1497.          i <= CrsrLibEntry -> NumOfPins;
  1498.          i++) {
  1499.         y = y1 + PinWidth / 2 + (i - CrsrLibEntry -> NumOfPins / 2 - 1) *
  1500.                                 PinWidth;
  1501.         MapX1 = PartX + TransMat[0][0] * x2 + TransMat[0][1] * y;
  1502.         MapY1 = PartY + TransMat[1][0] * x2 + TransMat[1][1] * y;
  1503.         MapX2 = PartX + TransMat[0][0] * (x2 + PIN_LENGTH) + TransMat[0][1] * y;
  1504.         MapY2 = PartY + TransMat[1][0] * (x2 + PIN_LENGTH) + TransMat[1][1] * y;
  1505.         GRMoveTo(MapX1, MapY1);
  1506.         GRLineTo(MapX2, MapY2);
  1507.     }
  1508.     }
  1509.     GRSetColor(LastColor);
  1510. }
  1511.  
  1512. /*****************************************************************************
  1513. * Returns TRUE iff the given library item chip name is drawable.         *
  1514. *****************************************************************************/
  1515. BooleanType CanDrawChipName(char *LibName)
  1516. {
  1517.     char Line[LINE_LEN_SHORT];
  1518.     LibraryEntryStruct *Entry;
  1519.  
  1520.     if ((Entry = FindLibPart(LibName)) == NULL) {
  1521.     sprintf(Line, "Failed to find part \"%s\" in library", LibName);
  1522.         IntrQueryContinue(Line, EEPopUpFrameColor,
  1523.                   EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
  1524.                           EEWindowsFrameWidth, &Cursor, INTR_WNDW_PLACE_CENTER);
  1525.     return FALSE;
  1526.     }
  1527.     return Entry -> DrawName;
  1528. }
  1529.