home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / editors / eedraw / src / eep / eelibs2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-29  |  13.9 KB  |  408 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 <string.h>
  10. #include <time.h>
  11.  
  12. #ifdef __MSDOS__
  13. #include <stdlib.h>
  14. #include <conio.h>
  15. #include <dos.h>
  16. #include <alloc.h>
  17. #endif /* __MSDOS__ */
  18.  
  19. #include "program.h"
  20. #include "priorque.h"
  21. #include "eelibs.h"
  22. #include "eelibsl.h"
  23. #include "EELayer.h"
  24. #include "eeredraw.h"
  25. #include "eestring.h"
  26. #include "igraph.h"
  27. #include "primary.h"
  28.  
  29. enum {
  30.     TMENU_NONE = 10,
  31.     TMENU_ROTATE_R,
  32.     TMENU_ROTATE_L,
  33.     TMENU_MIRROR_X,
  34.     TMENU_MIRROR_Y
  35. };
  36.  
  37. static void DrawLibPartAux(LibraryEntryStruct *Entry, int PartX, int PartY,
  38.                         int TransMat[2][2], int Multi);
  39. static char *LookUpPinText(char *Pins, int PinNum);
  40. static void MapAngles(int *Angle1, int *Angle2, int TransMat[2][2]);
  41. static LibraryEntryStruct *FindLibPart(char *Name);
  42.  
  43. /*****************************************************************************
  44. * Routine to draw the given part at given position, transformed/mirror as    *
  45. * specified, and in the given drawing mode. Only this one is visible...         *
  46. *****************************************************************************/
  47. void DrawLibPart(DrawLibItemStruct *DrawLibItem)
  48. {
  49.     LibraryEntryStruct *Entry;
  50.     char Line[LINE_LEN];
  51.  
  52.     if ((Entry = FindLibPart(DrawLibItem -> ChipName)) == NULL) {
  53.     sprintf(Line, "Failed to find part \"%s\" in library",
  54.                         DrawLibItem -> ChipName);
  55.     FatalError(Line);
  56.     }
  57.  
  58.     DrawLibPartAux(Entry,
  59.            DrawLibItem -> PosX,
  60.            DrawLibItem -> PosY,
  61.            DrawLibItem -> Transform,
  62.            DrawLibItem -> Multi);
  63.  
  64.     if (Entry -> DrawName &&
  65.     DrawLibItem -> ChipNameOrient != TEXT_ORIENT_NON)
  66.     PutTextInfo(DrawLibItem -> ChipNameOrient,
  67.             DrawLibItem -> ChipNameX,
  68.             DrawLibItem -> ChipNameY,
  69.             1,
  70.             DrawLibItem -> ChipName);
  71.     if (DrawLibItem -> PartNameOrient != TEXT_ORIENT_NON)
  72.     PutTextInfo(DrawLibItem -> PartNameOrient,
  73.             DrawLibItem -> PartNameX,
  74.             DrawLibItem -> PartNameY,
  75.             1,
  76.             DrawLibItem -> PartName);
  77. }
  78.  
  79. /*****************************************************************************
  80. * Routine to find a part in one of the libraries given its name.         *
  81. *****************************************************************************/
  82. static LibraryEntryStruct *FindLibPart(char *Name)
  83. {
  84.     LibraryEntryStruct *Entry, DummyEntry;
  85.     LibraryStruct *Lib = LibraryList;
  86.  
  87.     DummyEntry.Pins = NULL;            /* Used only to call PQFind. */
  88.     DummyEntry.Drawings = NULL;
  89.     DummyEntry.Multi = NULL;
  90.     strcpy(DummyEntry.Name, Name);
  91.  
  92.     PQCompFunc((PQCompFuncType) LibraryEntryCompare);
  93.  
  94.     while (Lib) {
  95.     if ((Entry = (LibraryEntryStruct *) PQFind(Lib -> Entries,
  96.                            (VoidPtr) &DummyEntry))
  97.         != NULL)
  98.         return Entry;
  99.  
  100.     Lib = Lib -> Pnext;
  101.     }
  102.     return NULL;
  103. }
  104.  
  105. /*****************************************************************************
  106. * Routine to draw the given part at given position, transformed/mirror as    *
  107. * specified, and in the given drawing mode.                     *
  108. *****************************************************************************/
  109. static void DrawLibPartAux(LibraryEntryStruct *Entry, int PartX, int PartY,
  110.                         int TransMat[2][2], int Multi)
  111. {
  112.     int i, x1, y1, x2, y2, IsMulti, *NextPinMulti, NextPinNum, t1, t2,
  113.     y, MapX1, MapY1, MapX2, MapY2, PinWidth, *Poly;
  114.     char Line[LINE_LEN], *NextPinText;
  115.     LibraryDrawEntryStruct *DEntry;
  116.  
  117.     IsMulti = Entry -> NumOfUnits > 0;
  118.     if (IsMulti) {
  119.     /* Make NextMulti point on next pin number in multi array: */
  120.     NextPinMulti = &Entry -> Multi[Entry -> PinsPerUnit * --Multi];
  121.  
  122.     NextPinText = NULL;
  123.     }
  124.     else {
  125.     NextPinNum = 1;
  126.     NextPinMulti = NULL;
  127.  
  128.     /* Make a copy of all pin text info so we can use strtok routine on: */
  129.     strncpy(Line, Entry -> Pins, LINE_LEN - 1);
  130.     NextPinText = strtok(Line, PIN_SEPERATOR);
  131.     }
  132.  
  133.     if (Entry -> Drawings != NULL) {
  134.     DEntry = Entry -> Drawings;
  135.     while (DEntry != NULL) {
  136.         switch (DEntry -> DrawType) {
  137.         case ARC_DRAW_TYPE:
  138.                 if(!ReturnLayerMode(DEntry->Layer))
  139.                 break;
  140.             t1 = DEntry -> U.Arc.t1;
  141.             t2 = DEntry -> U.Arc.t2;
  142.             MapAngles(&t1, &t2, TransMat);
  143.             IGArc(PartX + TransMat[0][0] * DEntry -> U.Arc.x +
  144.                   TransMat[0][1] * DEntry -> U.Arc.y,
  145.               PartY + TransMat[1][0] * DEntry -> U.Arc.x +
  146.                   TransMat[1][1] * DEntry -> U.Arc.y,
  147.               t1,
  148.               t2,
  149.               DEntry -> U.Arc.r);
  150.             break;
  151.         case CIRCLE_DRAW_TYPE:
  152.                 if(!ReturnLayerMode(DEntry->Layer))
  153.                 break;
  154.             IGCircle(PartX + TransMat[0][0] * DEntry -> U.Circ.x +
  155.                      TransMat[0][1] * DEntry -> U.Circ.y,
  156.                  PartY + TransMat[1][0] * DEntry -> U.Circ.x +
  157.                      TransMat[1][1] * DEntry -> U.Circ.y,
  158.                  DEntry -> U.Circ.r);
  159.             break;
  160.         case TEXT_DRAW_TYPE:
  161.                  if(!ReturnLayerMode(DEntry->Layer))
  162.                 break;
  163.  
  164.             /* The text orientation may need to be flipped if the    */
  165.             /* transformation matrix cuases xy axes to be flipped.   */
  166.             t1 = (TransMat[0][0] == 0) ^ (DEntry -> U.Text.Horiz !=
  167.                           TEXT_ORIENT_HORIZ);
  168.             x1 = PartX + TransMat[0][0] * DEntry -> U.Text.x
  169.                    + TransMat[0][1] * DEntry -> U.Text.y;
  170.             y1 = PartY + TransMat[1][0] * DEntry -> U.Text.x
  171.                    + TransMat[1][1] * DEntry -> U.Text.y;
  172.             PutTextInfo(t1 ? TEXT_ORIENT_HORIZ : TEXT_ORIENT_VERT,
  173.                 x1, y1,    1, DEntry -> U.Text.Text);
  174.             break;
  175.         case SQUARE_DRAW_TYPE:
  176.                  if(!ReturnLayerMode(DEntry->Layer))
  177.                 break; 
  178.             x1 = PartX + TransMat[0][0] * DEntry -> U.Sqr.x1
  179.                    + TransMat[0][1] * DEntry -> U.Sqr.y1;
  180.             y1 = PartY + TransMat[1][0] * DEntry -> U.Sqr.x1
  181.                    + TransMat[1][1] * DEntry -> U.Sqr.y1;
  182.             x2 = PartX + TransMat[0][0] * DEntry -> U.Sqr.x2
  183.                    + TransMat[0][1] * DEntry -> U.Sqr.y2;
  184.             y2 = PartY + TransMat[1][0] * DEntry -> U.Sqr.x2
  185.                    + TransMat[1][1] * DEntry -> U.Sqr.y2;
  186.             IGMoveTo(x1, y1);
  187.             IGLineTo(x1, y2);
  188.             IGLineTo(x2, y2);
  189.             IGLineTo(x2, y1);
  190.             IGLineTo(x1, y1);
  191.             break;
  192.         case LINE_DRAW_TYPE:
  193.                  if(!ReturnLayerMode(DEntry->Layer))
  194.                 break; 
  195.             x1 = PartX + TransMat[0][0] * DEntry -> U.Line.x1
  196.                    + TransMat[0][1] * DEntry -> U.Line.y1;
  197.             y1 = PartY + TransMat[1][0] * DEntry -> U.Line.x1
  198.                    + TransMat[1][1] * DEntry -> U.Line.y1;
  199.             x2 = PartX + TransMat[0][0] * DEntry -> U.Line.x2
  200.                    + TransMat[0][1] * DEntry -> U.Line.y2;
  201.             y2 = PartY + TransMat[1][0] * DEntry -> U.Line.x2
  202.                    + TransMat[1][1] * DEntry -> U.Line.y2;
  203.             if (DEntry -> U.Line.Invert) {
  204.             MapX1 = SIGN(x2 - x1);
  205.             MapY1 = SIGN(y2 - y1);
  206.             IGCircle(MapX1 * INVERT_PIN_RADIUS + x1,
  207.                  MapY1 * INVERT_PIN_RADIUS + y1,
  208.                  INVERT_PIN_RADIUS);
  209.             IGMoveTo(MapX1 * INVERT_PIN_RADIUS * 2 + x1,
  210.                  MapY1 * INVERT_PIN_RADIUS * 2 + y1);
  211.             IGLineTo(x2, y2);
  212.             }
  213.             else {
  214.             IGMoveTo(x1, y1);
  215.             IGLineTo(x2, y2);
  216.             }
  217.             if (IsMulti & ReturnLayerMode(LAYER_PIN)) {
  218.             PutLineTextInfo(x1, y1, x2, y2,
  219.                 LookUpPinText(Entry -> Pins, *NextPinMulti),
  220.                 *NextPinMulti,
  221.                 Entry -> TextInside,
  222.                 Entry -> DrawNums);
  223.             NextPinMulti++;
  224.             }
  225.             else {
  226.             PutLineTextInfo(x1, y1, x2, y2,
  227.                 NextPinText,
  228.                 NextPinNum,
  229.                 Entry -> TextInside,
  230.                 Entry -> DrawNums);
  231.             NextPinText = strtok(NULL, PIN_SEPERATOR);
  232.             NextPinNum++;
  233.             }
  234.             break;
  235.         case POLYLINE_DRAW_TYPE:
  236.                 if(!ReturnLayerMode(DEntry->Layer))
  237.                 break;
  238.             Poly = (int *) MyMalloc(sizeof(int) * 2 *
  239.                             DEntry -> U.Poly.n);
  240.             for (i = 0; i < DEntry -> U.Poly.n; i++) {
  241.             Poly[i * 2] = PartX +
  242.                 TransMat[0][0] * DEntry -> U.Poly.PolyList[i * 2] +
  243.                 TransMat[0][1] * DEntry -> U.Poly.PolyList[i * 2 + 1];
  244.             Poly[i * 2 + 1] = PartY +
  245.                 TransMat[1][0] * DEntry -> U.Poly.PolyList[i * 2] +
  246.                 TransMat[1][1] * DEntry -> U.Poly.PolyList[i * 2 + 1];
  247.             }
  248.             IGPoly(DEntry -> U.Poly.n, Poly, DEntry -> U.Poly.Fill);
  249.             MyFree((VoidPtr) Poly);
  250.             break;
  251.         }
  252.         DEntry = DEntry -> Pnext;
  253.     }
  254.     }
  255.     else {          /* NULL Drawing - draw simple a box with all pins: */
  256.     y1 = Entry -> TextInside ? PIN_WIDTH * Entry -> NumOfPins / 4 :
  257.                    PIN_WIDTH * Entry -> NumOfPins / 2;
  258.     x1 = Entry -> TextInside ? (int) (y1 * CHIP_BOX_ASPECT_TI) :
  259.                    (int) (y1 * CHIP_BOX_ASPECT_TO);
  260.         /* But make sure we can still print somethings inside... */
  261.     if (x1 < DRAW_TEXT_WIDTH * 12) x1 = DRAW_TEXT_WIDTH * 12;
  262.     x2 = x1 / 2;
  263.     y2 = y1 / 2;
  264.     x1 = -x2;
  265.     y1 = -y2;
  266.     PinWidth = Entry -> TextInside ? PIN_WIDTH / 2 : PIN_WIDTH;
  267.     if(ReturnLayerMode(LAYER_GATE)){
  268.         IGMoveTo(PartX + TransMat[0][0] * x1 + TransMat[0][1] * y1,
  269.              PartY + TransMat[1][0] * x1 + TransMat[1][1] * y1);
  270.         IGLineTo(PartX + TransMat[0][0] * x1 + TransMat[0][1] * y2,
  271.              PartY + TransMat[1][0] * x1 + TransMat[1][1] * y2);
  272.         IGLineTo(PartX + TransMat[0][0] * x2 + TransMat[0][1] * y2,
  273.              PartY + TransMat[1][0] * x2 + TransMat[1][1] * y2);
  274.         IGLineTo(PartX + TransMat[0][0] * x2 + TransMat[0][1] * y1,
  275.              PartY + TransMat[1][0] * x2 + TransMat[1][1] * y1);
  276.         IGLineTo(PartX + TransMat[0][0] * x1 + TransMat[0][1] * y1,
  277.              PartY + TransMat[1][0] * x1 + TransMat[1][1] * y1);
  278.         for (i = 0; i < Entry -> NumOfPins / 2; i++) {
  279.             y = y2 - PinWidth / 2 - i * PinWidth;
  280.             MapX1 = PartX + TransMat[0][0] * x1 + TransMat[0][1] * y;
  281.             MapY1 = PartY + TransMat[1][0] * x1 + TransMat[1][1] * y;
  282.             MapX2 = PartX + TransMat[0][0] * (x1 - PIN_LENGTH) + TransMat[0][1] * y;
  283.             MapY2 = PartY + TransMat[1][0] * (x1 - PIN_LENGTH) + TransMat[1][1] * y;
  284.             IGMoveTo(MapX1, MapY1);
  285.             IGLineTo(MapX2, MapY2);
  286.             if (IsMulti & ReturnLayerMode(LAYER_PINNUM)) {
  287.             PutLineTextInfo(MapX1, MapY1, MapX2, MapY2,
  288.                 LookUpPinText(Entry -> Pins, *NextPinMulti),
  289.                 *NextPinMulti,
  290.                 Entry -> TextInside,
  291.                 Entry -> DrawNums);
  292.             NextPinMulti++;
  293.             }
  294.            else if(ReturnLayerMode(LAYER_PINNUM)) {
  295.             PutLineTextInfo(MapX1, MapY1, MapX2, MapY2,
  296.                 NextPinText,
  297.                 NextPinNum,
  298.                 Entry -> TextInside,
  299.                         Entry -> DrawNums);
  300.             NextPinText = strtok(NULL, PIN_SEPERATOR);
  301.             NextPinNum++;
  302.             }
  303.         }
  304.     }
  305.     for (i = Entry -> NumOfPins / 2 + 1; i <= Entry -> NumOfPins; i++) {
  306.         y = y1 + PinWidth / 2 + (i - Entry -> NumOfPins / 2 - 1) *
  307.                                 PinWidth;
  308.         MapX1 = PartX + TransMat[0][0] * x2 + TransMat[0][1] * y;
  309.         MapY1 = PartY + TransMat[1][0] * x2 + TransMat[1][1] * y;
  310.         MapX2 = PartX + TransMat[0][0] * (x2 + PIN_LENGTH) + TransMat[0][1] * y;
  311.         MapY2 = PartY + TransMat[1][0] * (x2 + PIN_LENGTH) + TransMat[1][1] * y;
  312.         if(ReturnLayerMode(LAYER_GATE)){
  313.             IGMoveTo(MapX1, MapY1);
  314.             IGLineTo(MapX2, MapY2);
  315.         }
  316.         if (IsMulti & ReturnLayerMode(LAYER_PINNUM)) {
  317.         PutLineTextInfo(MapX1, MapY1, MapX2, MapY2,
  318.             LookUpPinText(Entry -> Pins, *NextPinMulti),
  319.             *NextPinMulti,
  320.             Entry -> TextInside,
  321.                     Entry -> DrawNums);
  322.         NextPinMulti++;
  323.         }
  324.         else if(ReturnLayerMode(LAYER_PINNUM)) {
  325.         PutLineTextInfo(MapX1, MapY1, MapX2, MapY2,
  326.             NextPinText,
  327.             NextPinNum,
  328.             Entry -> TextInside,
  329.                     Entry -> DrawNums);
  330.         NextPinText = strtok(NULL, PIN_SEPERATOR);
  331.         NextPinNum++;
  332.         }
  333.     }
  334.     }
  335. }
  336.  
  337. /*****************************************************************************
  338. * Given the Pins string and PinNum returns NULL terminated string of that    *
  339. * pin allocated statically.                             *
  340. *****************************************************************************/
  341. static char *LookUpPinText(char *Pins, int PinNum)
  342. {
  343.     static char Pin[MAX_PIN_INFO];
  344.     int i, Count = 1;
  345.  
  346.     while (*Pins && Count != PinNum) {
  347.     if (*Pins++ == PIN_SEPERATOR[0]) Count++;
  348.     }
  349.  
  350.     if (*Pins) {
  351.     i = 0;
  352.     while (i < MAX_PIN_INFO - 1 && *Pins != PIN_SEPERATOR[0] && *Pins != 0)
  353.         Pin[i++] = *Pins++;
  354.     Pin[i] = 0;
  355.     return i > 0 ? Pin : NULL;
  356.     }
  357.     else {
  358.     return NULL;
  359.     }
  360. }
  361.  
  362. /*****************************************************************************
  363. * Routine to rotate the given angular direction by the given Transformation. *
  364. * Input (and output) angles must be as follows:                     *
  365. * Angle1 in [0..360], Angle2 > Angle1 in [0..720]. Arc is assumed to be less *
  366. * than 180 degrees.                                 *
  367. * Algorithm:                                     *
  368. * Map the angles to a point on the unit circle which is mapped using the     *
  369. * transform (only mirror and rotate so it remains on the unit circle) to     *
  370. * a new point which is used to detect new angle.                 *
  371. *****************************************************************************/
  372. static void MapAngles(int *Angle1, int *Angle2, int TransMat[2][2])
  373. {
  374.     int Angle;
  375.     RealType x, y, t;
  376.  
  377.     x = cos(*Angle1 * M_PI / 180.0);
  378.     y = sin(*Angle1 * M_PI / 180.0);
  379.     t = x * TransMat[0][0] + y * TransMat[0][1];
  380.     y = x * TransMat[1][0] + y * TransMat[1][1];
  381.     x = t;
  382.     *Angle1 = (int) (atan2(y, x) * 180.0 / M_PI + 0.5);
  383.  
  384.     x = cos(*Angle2 * M_PI / 180.0);
  385.     y = sin(*Angle2 * M_PI / 180.0);
  386.     t = x * TransMat[0][0] + y * TransMat[0][1];
  387.     y = x * TransMat[1][0] + y * TransMat[1][1];
  388.     x = t;
  389.     *Angle2 = (int) (atan2(y, x) * 180.0 / M_PI + 0.5);
  390.  
  391.     NORMALIZE_ANGLE(*Angle1);
  392.     NORMALIZE_ANGLE(*Angle2);
  393.     if (*Angle2 < *Angle1) *Angle2 += 360;
  394.  
  395.     if (*Angle2 - *Angle1 > 180) {         /* Need to swap the two angles. */
  396.     Angle = (*Angle1);
  397.     *Angle1 = (*Angle2);
  398.     *Angle2 = Angle;
  399.  
  400.     NORMALIZE_ANGLE(*Angle1);
  401.     NORMALIZE_ANGLE(*Angle2);
  402.     if (*Angle2 < *Angle1) *Angle2 += 360;
  403.     }
  404.  
  405.     *Angle1 -= 1;    /* As the angles loaded are decreased by 1 when loaded. */
  406.     *Angle2 += 1;
  407. }
  408.