home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / GRAPHICS / MISC / EEDPR23S.ZIP / EELIBS1.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-10  |  18.9 KB  |  588 lines

  1. /*****************************************************************************
  2. *   Module to handle libraries (first part - file and io).             *
  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 <dir.h>
  17. #include <alloc.h>
  18. #else
  19. #include <ctype.h>
  20. char *strupr(char *s);
  21. char *strlwr(char *s);
  22. #endif /* __MSDOS__ */
  23.  
  24. #include "program.h"
  25. #include "priorque.h"
  26. #include "eelibs.h"
  27. #include "eelibsl.h"
  28. #include "eeredraw.h"
  29. #include "igraph.h"
  30.  
  31. LibraryStruct *LibraryList = NULL;        /* All part libs are saved here. */
  32.  
  33. static char *GetLine(FILE *f, char *Line, int *LineNum);
  34. static PriorQue *LoadLibraryAux(FILE *f, int *NumOfParts);
  35. static char *GetPinsEntry(FILE *f, char *Line, int *LineNum, int NumOfPins);
  36. static int *GetMultiEntry(FILE *f, char *Line, int *LineNum, int NumOfUnits,
  37.                             int PinsPerUnit);
  38. static LibraryDrawEntryStruct *GetDrawEntry(FILE *f, char *Line, int *LineNum,
  39.             BooleanType *HasLines, LibraryEntryStruct *LibEnrty);
  40. static void UpdateBBox(LibraryEntryStruct *LibEntry, int x, int y);
  41. static LibraryStruct *FindLibrary(char *Name);
  42.  
  43. /*****************************************************************************
  44. * Routine to load the given library name. FullLibName should hold full path  *
  45. * of file name to open, while LibName should hold only its name.         *
  46. *****************************************************************************/
  47. void LoadLibraryName(char *FullLibName, char *LibName)
  48. {
  49.     int NumOfParts;
  50.     char Line[LINE_LEN_SHORT];
  51.     FILE *f;
  52.     LibraryStruct *NewLib;
  53.     PriorQue *Entries;
  54.  
  55.     /* Dont reload same library twice: */
  56.     if (FindLibrary(LibName) != NULL) return;
  57.  
  58.     f = fopen(FullLibName, "rt");
  59.     if (f == NULL) {
  60.     sprintf(Line, "Failed to open library \"%s\".\n", FullLibName);
  61.     FatalError(Line);
  62.     }
  63.  
  64.     fprintf(stderr, "Reading library \"%s\".\n", FullLibName);
  65.  
  66.     if ((Entries = LoadLibraryAux(f, &NumOfParts)) != NULL) {
  67.     NewLib = (LibraryStruct *) MyMalloc(sizeof(LibraryStruct));
  68.     NewLib -> Entries = Entries;
  69.     NewLib -> NumOfParts = NumOfParts;
  70.     strcpy(NewLib -> Name, LibName);
  71.     NewLib -> Pnext = LibraryList;
  72.     LibraryList = NewLib;
  73.     }
  74.     fclose(f);
  75. }
  76.  
  77. /*****************************************************************************
  78. * Routine to load all libraries specified lin LoadLibraryList which assumes  *
  79. * to hold names of libraries to load, seperated by commas and with no lib    *
  80. * extension. Note we dont use strtok inside the loop as LoadLibraryName uses *
  81. * it internally.                                 *
  82. *****************************************************************************/
  83. void LoadLibraries(char *LoadLibraryList)
  84. {
  85.     char *p, *NextLibName, Name[LINE_LEN_SHORT],
  86.     *LibName = LoadLibraryList;
  87.  
  88.     if (!strtok(LibName, "\n\r") || strlen(LibName) == 0) return;
  89.  
  90.     do {
  91.     if ((NextLibName = strchr(LibName, ',')) != NULL) {
  92.         NextLibName[0] = 0;
  93.         NextLibName = &NextLibName[1];
  94.     }
  95.     strlwr(LibName);
  96.     strcpy(Name, LibName);
  97.     if ((p = strrchr(Name, '.')) != NULL && strlen(p) < 5) *p = 0;
  98.     strcat(Name, ".lib");
  99.     if ((p = searchpath(Name)) == NULL) {
  100.         char Line[LINE_LEN];
  101.  
  102.         sprintf(Line, "Failed to find library \"%s\"\n", Name);
  103.         FatalError(Line);
  104.     }
  105.  
  106.     LoadLibraryName(p, LibName);
  107.  
  108.     LibName = NextLibName;
  109.     }
  110.     while (LibName != NULL);
  111. }
  112.  
  113. /*****************************************************************************
  114. * Routine to read one line from given file.                     *
  115. *****************************************************************************/
  116. static char *GetLine(FILE *f, char *Line, int *LineNum)
  117. {
  118.     do {
  119.     if (fgets(Line, LINE_LEN - 1, f) == NULL) return NULL;
  120.     ++*LineNum;
  121.     }
  122.     while (Line[0] == '#' || Line[0] == '\n' || Line[0] == 0);
  123.  
  124.     return Line;
  125. }
  126.  
  127. /*****************************************************************************
  128. * Routine to compare two LibraryEntryStruct for the PriorQue module.         *
  129. * Comparison is based on Part name.                         *
  130. *****************************************************************************/
  131. int LibraryEntryCompare(LibraryEntryStruct *LE1,
  132.             LibraryEntryStruct *LE2)
  133. {
  134.     return strcmp(LE1 -> Name, LE2 -> Name);
  135. }
  136.  
  137. /*****************************************************************************
  138. * Routine to load a library from given open file.                 *
  139. *****************************************************************************/
  140. static PriorQue *LoadLibraryAux(FILE *f, int *NumOfParts)
  141. {
  142.     int LineNum = 0;
  143.     char Line[LINE_LEN], *p, *Name, *Prefix;
  144.     BooleanType Res, HasLines;
  145.     PriorQue
  146.     *PQ = NULL;
  147.     LibraryEntryStruct *LibEntry;
  148.  
  149.     *NumOfParts = 0;
  150.  
  151.     if (GetLine(f, Line, &LineNum) == NULL ||
  152.     strncmp(Line, FILE_IDENT, sizeof(FILE_IDENT) - 1) != 0) {
  153.     FatalError("File is NOT EEDRAW library!");
  154.     }
  155.  
  156.     PQInit(&PQ);
  157.     PQCompFunc((PQCompFuncType) LibraryEntryCompare);
  158.  
  159.     while (GetLine(f, Line, &LineNum)) {
  160.     p = strtok(Line, " \t\n");
  161.  
  162.     if (strcmp(p, "DEF") != 0) {
  163.         sprintf(Line, "DEF command expected in line %d, aborted.",
  164.                                 LineNum);
  165.         FatalError(Line);
  166.     }
  167.     else {
  168.         /* Read one DEF/ENDDEF part entry from library: */
  169.         LibEntry = (LibraryEntryStruct *)
  170.                     MyMalloc(sizeof(LibraryEntryStruct));
  171.         LibEntry -> BBoxMinX = LibEntry -> BBoxMaxX =
  172.         LibEntry -> BBoxMinY = LibEntry -> BBoxMaxY = 0;
  173.         LibEntry -> Pins = NULL;
  174.         LibEntry -> Drawings = NULL;
  175.         LibEntry -> Multi = NULL;
  176.  
  177.         if ((Name = strtok(NULL, " \t\n")) == NULL ||      /* Part name: */
  178.         (Prefix = strtok(NULL, " \t\n")) == NULL ||  /* Prefix name: */
  179.         (p = strtok(NULL, " \t\n")) == NULL ||         /* NumOfPins: */
  180.         sscanf(p, "%d", &LibEntry -> NumOfPins) != 1 ||
  181.         (p = strtok(NULL, " \t\n")) == NULL ||        /* TextInside: */
  182.         sscanf(p, "%d", &LibEntry -> TextInside) != 1 ||
  183.         (p = strtok(NULL, " \t\n")) == NULL ||            /* DrawNums: */
  184.         sscanf(p, "%d", &LibEntry -> DrawNums) != 1 ||
  185.         (p = strtok(NULL, " \t\n")) == NULL ||        /* NumOfUnits: */
  186.         sscanf(p, "%d", &LibEntry -> NumOfUnits) != 1 ||
  187.         (LibEntry -> NumOfUnits > 0 &&
  188.          ((p = strtok(NULL, " \t\n")) == NULL ||     /* PinsPerUnit: */
  189.            sscanf(p, "%d", &LibEntry -> PinsPerUnit) != 1)) ||
  190.         strlen(Name) > PART_NAME_LEN ||
  191.         strlen(Prefix) > PREFIX_NAME_LEN) {
  192.         sprintf(Line, "Wrong DEF format in line %d, aborted.",
  193.                                 LineNum);
  194.         FatalError(Line);
  195.         }
  196.         else {
  197.         /* Copy part name and prefix. */
  198.         strupr(Name);
  199.         if ((LibEntry -> DrawName = Name[0] != '~') != FALSE)
  200.             strcpy(LibEntry -> Name, Name);
  201.         else
  202.             strcpy(LibEntry -> Name, &Name[1]);
  203.         if (strcmp(Prefix, "~") == 0)
  204.             LibEntry -> Prefix[0] = 0;
  205.         else
  206.             strcpy(LibEntry -> Prefix, Prefix);
  207.         }
  208.  
  209.         HasLines = FALSE;
  210.         while (TRUE) {
  211.         GetLine(f, Line, &LineNum);
  212.         p = strtok(Line, " \t\n");
  213.  
  214.         Res = TRUE;
  215.         if (strcmp(p, "ENDDEF") == 0) {
  216.             ++*NumOfParts;
  217.             break;
  218.         }
  219.         else if (strcmp(p, "DRAW") == 0)
  220.             Res = (LibEntry -> Drawings =
  221.                GetDrawEntry(f, Line, &LineNum, &HasLines,
  222.                                LibEntry)) != NULL;
  223.         else if (strcmp(p, "PINS") == 0)
  224.             Res = (LibEntry -> Pins =
  225.                GetPinsEntry(f, Line, &LineNum,
  226.                     LibEntry -> NumOfPins)) != NULL;
  227.         else if (strcmp(p, "MULTI") == 0) {
  228.             if (LibEntry -> NumOfUnits > 0)
  229.             Res = (LibEntry -> Multi =
  230.                    GetMultiEntry(f, Line, &LineNum,
  231.                          LibEntry -> NumOfUnits,
  232.                          LibEntry -> PinsPerUnit)) != NULL;
  233.             else {
  234.             sprintf(Line, "MULTI found in DEF with #Units = 0 in line %d, aborted.",
  235.                                 LineNum);
  236.             FatalError(Line);
  237.             }
  238.         }
  239.         else {
  240.             sprintf(Line, "Undefined command \"%s\" in line %d, aborted.",
  241.                                 p, LineNum);
  242.             FatalError(Line);
  243.         }
  244.  
  245.         if (!Res) {              /* Something went wrong there. */
  246.             FatalError("Wrong format");        /* Should die before! */
  247.         }
  248.         }
  249.         if (LibEntry -> Pins == NULL && HasLines) {
  250.         sprintf(Line, "No PINS defined for part in line %d, aborted.",
  251.                                 LineNum);
  252.         FatalError(Line);
  253.         }
  254.         if (LibEntry -> NumOfUnits > 0) {
  255.         if (LibEntry -> Multi == NULL) {
  256.             sprintf(Line, "No MULTI defined for part in line %d, aborted.",
  257.                                 LineNum);
  258.             FatalError(Line);
  259.         }
  260.         if (LibEntry -> Drawings == NULL) {
  261.             sprintf(Line, "No DRAW defined for part in line %d, aborted.",
  262.                                 LineNum);
  263.             FatalError(Line);
  264.         }
  265.         }
  266.         if (LibEntry -> Drawings == NULL) {
  267.         /* Initialize BBox manually - its only a box with pins: */
  268.         LibEntry -> BBoxMaxX = LibEntry -> BBoxMaxY =
  269.            PIN_WIDTH * LibEntry -> NumOfPins / 2 + PIN_LENGTH;
  270.         LibEntry -> BBoxMinX = LibEntry -> BBoxMinY =
  271.             -LibEntry -> BBoxMaxX;
  272.         }
  273.  
  274.         /* If we are here, this part is O.k. - put it in: */
  275.         PQInsert(&PQ, (VoidPtr) LibEntry);
  276.     }
  277.     }
  278.  
  279.     return PQ;
  280. }
  281.  
  282. /*****************************************************************************
  283. * Routine to load a PINS definition from given file. Note "PINS" line has    *
  284. * been read already. Reads upto and include ENDPINS, or an error (NULL ret). *
  285. *****************************************************************************/
  286. static char *GetPinsEntry(FILE *f, char *Line, int *LineNum, int NumOfPins)
  287. {
  288.     int i;
  289.     char *p, Pins[LINE_LEN];
  290.  
  291.     Pins[0] = 0;
  292.     for (i = 0; i < NumOfPins; i++) {
  293.     if (GetLine(f, Line, LineNum) == NULL) {
  294.         FatalError("File ended prematurely");
  295.     }
  296.  
  297.     p = strtok(Line, "\n");             /* Remove the CR from line end. */
  298.     if (strcmp(p, "ENDPINS") == 0) {
  299.         sprintf(Line, "ENDPINS too soon (not enough pins) in line %d, aborted.", *LineNum);
  300.         FatalError(Line);
  301.     }
  302.     if ((p[0] == '~' && strlen(p) == 1))           /* Empty line ("~") ? */
  303.         strcat(Pins, "~");
  304.     else
  305.         strcat(Pins, p);
  306.     strcat(Pins, PIN_SEPERATOR);
  307.     if (strlen(Pins) > LINE_LEN - 10) {
  308.         sprintf(Line, "Pin definitions are too long in line %d, aborted.",
  309.                                 *LineNum);
  310.         FatalError(Line);
  311.     }
  312.     }
  313.  
  314.     if (GetLine(f, Line, LineNum) == NULL) {
  315.     FatalError("File ended prematurely");
  316.     }
  317.     p = strtok(Line, " \t\n");
  318.     if (strcmp(p, "ENDPINS") != 0) {
  319.     sprintf(Line, "ENDPINS expected in line %d, aborted.", *LineNum);
  320.     FatalError(Line);
  321.     }
  322.  
  323.     return strdup(Pins);
  324. }
  325.  
  326. /*****************************************************************************
  327. * Routine to load a MULTI definition from given file. Note "MULTI" line has  *
  328. * been read already. Reads upto and include ENDMULTI, or an error (NULL ret).*
  329. *****************************************************************************/
  330. static int *GetMultiEntry(FILE *f, char *Line, int *LineNum, int NumOfUnits,
  331.                             int PinsPerUnit)
  332. {
  333.     int i, j, *Array,
  334.     Count = 0;
  335.     char *p;
  336.  
  337.     Array = (int *) MyMalloc(sizeof(int) * NumOfUnits * PinsPerUnit);
  338.  
  339.     for (i = 0; i < NumOfUnits; i++) {
  340.     if (GetLine(f, Line, LineNum) == NULL) {
  341.         FatalError("File ended prematurely");
  342.     }
  343.  
  344.     for (p = strtok(Line, " \t\n"), j = 0;
  345.          j < PinsPerUnit;
  346.          p = strtok(NULL, " \t\n"), j++) {
  347.         if (p == NULL ||
  348.         sscanf(p, "%d", &Array[Count++]) != 1) {
  349.         sprintf(Line, "MULTI has less pins than needed in line %d",
  350.                                 *LineNum);
  351.         FatalError(Line);
  352.         }
  353.     }
  354.     }
  355.  
  356.     if (GetLine(f, Line, LineNum) == NULL) {
  357.     FatalError("File ended prematurely");
  358.     }
  359.     p = strtok(Line, " \t\n");
  360.     if (strcmp(p, "ENDMULTI") != 0) {
  361.     sprintf(Line, "ENDMULTI expected in line %d, aborted.", *LineNum);
  362.     FatalError(Line);
  363.     }
  364.  
  365.     return Array;
  366. }
  367.  
  368. /*****************************************************************************
  369. * Routine to load a DRAW definition from given file. Note "DRAW" line has    *
  370. * been read already. Reads upto and include ENDDRAW, or an error (NULL ret). *
  371. *****************************************************************************/
  372. static LibraryDrawEntryStruct *GetDrawEntry(FILE *f, char *Line, int *LineNum,
  373.             BooleanType *HasLines, LibraryEntryStruct *LibEntry)
  374. {
  375.     int i;
  376.     char *p, Buffer[LINE_LEN_SHORT];
  377.     RealType r;
  378.     BooleanType
  379.     Error = FALSE;
  380.     LibraryDrawEntryStruct *Tail, *New,
  381.     *Head = NULL;
  382.  
  383.     HasLines = FALSE;
  384.  
  385.     while (TRUE) {
  386.     if (GetLine(f, Line, LineNum) == NULL) {
  387.         FatalError("File ended prematurely");
  388.     }
  389.  
  390.     if (strncmp(Line, "ENDDRAW", 7) == 0) break;
  391.  
  392.     New = (LibraryDrawEntryStruct *)
  393.                 MyMalloc(sizeof(LibraryDrawEntryStruct));
  394.     New -> Pnext = NULL;
  395.  
  396.     switch (Line[0]) {
  397.         case 'A': /* Arc */
  398.         New -> DrawType = ARC_DRAW_TYPE;
  399.         Error = sscanf(&Line[2], "%d %d %d %d %d",
  400.             &New -> U.Arc.x, &New -> U.Arc.y, &New -> U.Arc.r,
  401.             &New -> U.Arc.t1, &New -> U.Arc.t2) != 5;
  402.         New ->U.Arc.x *= LIB_SCALE_DRAW;
  403.         New ->U.Arc.y *= LIB_SCALE_DRAW;
  404.         New ->U.Arc.r *= LIB_SCALE_DRAW;
  405.         NORMALIZE_ANGLE(New -> U.Arc.t1);
  406.         NORMALIZE_ANGLE(New -> U.Arc.t2);
  407.         if (New -> U.Arc.t1 > New -> U.Arc.t2)
  408.             New -> U.Arc.t2 += 360;
  409.         New -> U.Arc.t1 += 1; /* Force arc of 180 degree to be less. */
  410.         New -> U.Arc.t2 -= 1;
  411.  
  412.         /* Update the bbox: */
  413.         UpdateBBox(LibEntry, New -> U.Arc.x - New -> U.Arc.r,
  414.                      New -> U.Arc.y - New -> U.Arc.r);
  415.         UpdateBBox(LibEntry, New -> U.Arc.x + New -> U.Arc.r,
  416.                      New -> U.Arc.y + New -> U.Arc.r);
  417.         break;
  418.         case 'C': /* Circle */
  419.         New -> DrawType = CIRCLE_DRAW_TYPE;
  420.         Error = sscanf(&Line[2], "%d %d %d",
  421.             &New -> U.Circ.x, &New -> U.Circ.y, &New -> U.Circ.r) != 3;
  422.         New ->U.Circ.x *= LIB_SCALE_DRAW;
  423.         New ->U.Circ.y *= LIB_SCALE_DRAW;
  424.         New ->U.Circ.r *= LIB_SCALE_DRAW;
  425.         /* Update the bbox: */
  426.         UpdateBBox(LibEntry, New -> U.Circ.x - New -> U.Circ.r,
  427.                      New -> U.Circ.y - New -> U.Circ.r);
  428.         UpdateBBox(LibEntry, New -> U.Circ.x + New -> U.Circ.r,
  429.                      New -> U.Circ.y + New -> U.Circ.r);
  430.         break;
  431.         case 'T': /* Text */
  432.         New -> DrawType = TEXT_DRAW_TYPE;
  433.         Error = sscanf(&Line[2], "%d %d %d %s",
  434.                    &New -> U.Text.x, &New -> U.Text.y,
  435.                    &New -> U.Text.Horiz, Buffer) != 4;
  436.         if (!Error) {               /* Convert '~' to spaces. */
  437.             for (i = 0; i < strlen(Buffer); i++)
  438.             if (Buffer[i] == '~') Buffer[i] = ' ';
  439.             New -> U.Text.Text = strdup(Buffer);
  440.         }
  441.         New ->U.Text.x *= LIB_SCALE_DRAW;
  442.         New ->U.Text.y *= LIB_SCALE_DRAW;
  443.         break;
  444.         case 'S': /* Square */
  445.         New -> DrawType = SQUARE_DRAW_TYPE;
  446.         Error = sscanf(&Line[2], "%d %d %d %d",
  447.                    &New -> U.Sqr.x1, &New -> U.Sqr.y1,
  448.                    &New -> U.Sqr.x2, &New -> U.Sqr.y2) != 4;
  449.         New ->U.Sqr.x1 *= LIB_SCALE_DRAW;
  450.         New ->U.Sqr.y1 *= LIB_SCALE_DRAW;
  451.         New ->U.Sqr.x2 *= LIB_SCALE_DRAW;
  452.         New ->U.Sqr.y2 *= LIB_SCALE_DRAW;
  453.         break;
  454.         case 'L': /* Line */
  455.         *HasLines = TRUE;
  456.         New -> DrawType = LINE_DRAW_TYPE;
  457.         if ((i = sscanf(&Line[2], "%d %d %d %d %s",
  458.                 &New -> U.Line.x1, &New -> U.Line.y1,
  459.                 &New -> U.Line.x2, &New -> U.Line.y2,
  460.                 Buffer)) != 5)
  461.             i = sscanf(&Line[2], "%d %d %d %d",
  462.                    &New -> U.Line.x1, &New -> U.Line.y1,
  463.                    &New -> U.Line.x2, &New -> U.Line.y2);
  464.         Error = (i != 4 && i != 5) ||
  465.             (New -> U.Line.x1 != New -> U.Line.x2 &&
  466.              New -> U.Line.y1 != New -> U.Line.y2);
  467.         New ->U.Line.x1 *= LIB_SCALE_DRAW;
  468.         New ->U.Line.y1 *= LIB_SCALE_DRAW;
  469.         New ->U.Line.x2 *= LIB_SCALE_DRAW;
  470.         New ->U.Line.y2 *= LIB_SCALE_DRAW;
  471.         UpdateBBox(LibEntry, New -> U.Line.x1, New -> U.Line.y1);
  472.         UpdateBBox(LibEntry, New -> U.Line.x2, New -> U.Line.y2);
  473.         New -> U.Line.Invert = i == 5 && Buffer[0] == 'I';
  474.         break;
  475.         case 'P': /* Polyline */
  476.         New -> DrawType = POLYLINE_DRAW_TYPE;
  477.         New -> U.Poly.PolyList = NULL;
  478.         p = strtok(&Line[2], " \t\n");
  479.         if (sscanf(p, "%d", &New -> U.Poly.n) == 1 &&
  480.             New -> U.Poly.n > 0) {
  481.             New -> U.Poly.PolyList = (int *)
  482.             MyMalloc(sizeof(int) * New -> U.Poly.n * 2);
  483.             for (i = 0; i < New -> U.Poly.n * 2 && !Error; i++) {
  484.             p = strtok(NULL, " \t\n");
  485.             Error = sscanf(p, "%d", &New -> U.Poly.PolyList[i]) !=
  486.                                     1;
  487.             New ->U.Poly.PolyList[i] *= LIB_SCALE_DRAW;
  488.             if (i % 2 != 0)
  489.                 UpdateBBox(LibEntry, New -> U.Poly.PolyList[i-1],
  490.                          New -> U.Poly.PolyList[i]);
  491.             }
  492.             New -> U.Poly.Fill = (p = strtok(NULL, " \t\n")) != NULL &&
  493.                      p[0] == 'F';
  494.         }
  495.         else
  496.             Error = TRUE;
  497.         Error |= New -> U.Poly.Fill &&
  498.             (New -> U.Poly.PolyList[0] != New -> U.Poly.PolyList[i-2] ||
  499.              New -> U.Poly.PolyList[1] != New -> U.Poly.PolyList[i-1]);
  500.         if (Error && New -> U.Poly.PolyList)
  501.             MyFree((VoidPtr) New -> U.Poly.PolyList);
  502.         break;
  503.         default:
  504.         sprintf(Line, "Undefined DRAW command in line %d, aborted.",
  505.                                 *LineNum);
  506.         FatalError(Line);
  507.     }
  508.     if (Error) {
  509.         sprintf(Line, "Error in %c DRAW command in line %d, aborted.",
  510.                             Line[0], *LineNum);
  511.         FatalError(Line);
  512.     }
  513.     else {
  514.         if (Head == NULL)
  515.         Head = Tail = New;
  516.         else {
  517.         Tail -> Pnext = New;
  518.         Tail = New;
  519.         }
  520.     }
  521.     }
  522.  
  523.     /* Update the bbox to the maximum extrem as we may rotate the object. */
  524.     r = MAX(ABS(LibEntry->BBoxMinX), ABS(LibEntry->BBoxMaxX));
  525.     r = MAX(r, ABS(LibEntry->BBoxMinY));
  526.     r = MAX(r, ABS(LibEntry->BBoxMaxY));
  527.     LibEntry->BBoxMaxX = LibEntry->BBoxMaxY = r;
  528.     LibEntry->BBoxMinX = LibEntry->BBoxMinY = -r;
  529.  
  530.     return Head;
  531. }
  532.  
  533. /*****************************************************************************
  534. * Routine to update LibEntry bounding box accrding to given x, y value.         *
  535. *****************************************************************************/
  536. static void UpdateBBox(LibraryEntryStruct *LibEntry, int x, int y)
  537. {
  538.     if (LibEntry -> BBoxMinX > x) LibEntry -> BBoxMinX = x;
  539.     if (LibEntry -> BBoxMaxX < x) LibEntry -> BBoxMaxX = x;
  540.     if (LibEntry -> BBoxMinY > y) LibEntry -> BBoxMinY = y;
  541.     if (LibEntry -> BBoxMaxY < y) LibEntry -> BBoxMaxY = y;
  542. }
  543.  
  544. /*****************************************************************************
  545. * Routine to find the library given its name.                     *
  546. *****************************************************************************/
  547. static LibraryStruct *FindLibrary(char *Name)
  548. {
  549.     LibraryStruct
  550.     *Lib = LibraryList;
  551.  
  552.     while (Lib) {
  553.     if (strcmp(Name, Lib -> Name) == 0) return Lib;
  554.     Lib = Lib -> Pnext;
  555.     }
  556.     return NULL;
  557. }
  558.  
  559. #ifndef __MSDOS__
  560.  
  561. /*****************************************************************************
  562. * Routine to convert a string to all upper case:                 *
  563. *****************************************************************************/
  564. char *strupr(char *s)
  565. {
  566.     while (*s) {
  567.     if (islower(*s)) *s = toupper(*s);
  568.     s++;
  569.     }
  570.  
  571.     return s;
  572. }
  573.  
  574. /*****************************************************************************
  575. * Routine to convert a string to all upper case:                 *
  576. *****************************************************************************/
  577. char *strlwr(char *s)
  578. {
  579.     while (*s) {
  580.     if (isupper(*s)) *s = tolower(*s);
  581.     s++;
  582.     }
  583.  
  584.     return s;
  585. }
  586.  
  587. #endif /* __MSDOS__ */
  588.