home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / GRAPHICS / MISC / EEDRW23S.ZIP / EELOAD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-14  |  31.5 KB  |  957 lines

  1. /*****************************************************************************
  2. *   Module to load/save EEDraw files.                         *
  3. *                                         *
  4. * Written by:  Gershon Elber            IBM PC Ver 1.0,    Oct. 1989    *
  5. *****************************************************************************/
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <conio.h>
  10. #include <string.h>
  11. #include <dos.h>
  12. #include <alloc.h>
  13. #include "Program.h"
  14. #include "Director.h"
  15. #include "EELibs.h"
  16. #include "EEModify.h"
  17. #include "EERedraw.h"
  18. #include "EELoad.h"
  19.  
  20. #define EEDRAW_FILE_STAMP "EEDraw"
  21. #define NULL_STRING "_NONAME_"
  22. #define FILE_EXTENSION ".EED"
  23. #define NETLIST_FILE_EXTENSION ".NET"
  24.  
  25. static IntrCursorShapeStruct Cursor;
  26. static int GlblNumOfPolylines = 0;
  27.  
  28. static void GetPolylineNetList(DrawPolylineStruct *PolylineStruct,
  29.                    DrawGenericStruct *Phead,
  30.                    NetListStruct **NetListHead,
  31.                    BooleanType *IsABus);
  32. static void GetOnePolylineNetList(DrawPolylineStruct *PolylineStruct,
  33.                   DrawGenericStruct *Phead,
  34.                   NetListStruct **NetListHead,
  35.                   BooleanType *IsABus);
  36. static int StringComp(const void *Str1, const void *Str2);
  37. static BooleanType ConnectionExistsAtXY(DrawGenericStruct *Phead, int x, int y);
  38.  
  39. /*****************************************************************************
  40. * Routine to clear EEDraw drawing list of a window.                 *
  41. *****************************************************************************/
  42. BooleanType ClearDrawList(EEWindowStruct *Window)
  43. {
  44.     DrawGenericStruct *DrawStruct,
  45.         *EEDrawList = Window -> EEDrawList;
  46.  
  47.     Cursor.CursorType = INTR_CURSOR_ARROW;
  48.     if (!IntrQueryYesNo("Clear old data?", EEPopUpFrameColor,
  49.                     EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
  50.             EEWindowsFrameWidth, &Cursor,
  51.                         INTR_WNDW_PLACE_CENTER)) return FALSE;
  52.  
  53.     while (EEDrawList != NULL) {
  54.         DrawStruct = EEDrawList;
  55.     EEDrawList = EEDrawList -> Pnext;
  56.     FreeStruct(DrawStruct);
  57.     }
  58.  
  59.     Window -> EEDrawList = NULL;
  60.  
  61.     return TRUE;
  62. }
  63.  
  64. /*****************************************************************************
  65. * Routine to close the given window. Screen is NOT refreshed.             *
  66. *****************************************************************************/
  67. void CloseEEDFile(EEWindowStruct *Window)
  68. {
  69.     DrawGenericStruct *EEDrawList, *DrawStruct;
  70.  
  71.     if (Window == NULL) return;
  72.  
  73.     Cursor.CursorType = INTR_CURSOR_ARROW;
  74.  
  75.     IntrWndwDelete(Window -> IntrLibWindowID, FALSE);
  76.  
  77.     EEDrawList = Window -> EEDrawList;
  78.     while (EEDrawList != NULL) {
  79.     DrawStruct = EEDrawList;
  80.     EEDrawList = EEDrawList -> Pnext;
  81.     FreeStruct(DrawStruct);
  82.     }
  83.  
  84.     if (Window -> FileName != NULL);
  85.         MyFree(Window -> FileName);
  86. }
  87.  
  88. /*****************************************************************************
  89. * Routine to load an EEDraw file.                         *
  90. * IF Window -> FileName has not name (length 0) a file named is queried.     *
  91. * Returns TRUE if file has been loaded (at list partially.)             *
  92. *****************************************************************************/
  93. BooleanType LoadEEFile(EEWindowStruct *Window)
  94. {
  95.     char Line[LINE_LEN], Name1[LINE_LEN_SHORT], Name2[LINE_LEN_SHORT],
  96.                  Char1[LINE_LEN_SHORT], Char2[LINE_LEN_SHORT];
  97.     FileNameType *FileNames;
  98.     int i, NumOfFiles,
  99.     LineCount = 1;
  100.     BooleanType
  101.     Failed = FALSE;
  102.     DrawGenericStruct *Phead, *Pnext;
  103.     DrawLibItemStruct *LibItemStruct;
  104.     DrawConnectionStruct *ConnectionStruct;
  105.     DrawPolylineStruct *PolylineStruct;
  106.     DrawTextStruct *TextStruct;
  107.     FILE *f;
  108.  
  109.     Cursor.CursorType = INTR_CURSOR_ARROW;
  110.     sprintf(Line, "*%s", FILE_EXTENSION);
  111.     if (strlen(Window -> FileName) == 0) {
  112.     if ((FileNames = GetFileNamesDir(Line, ".", &NumOfFiles)) != NULL) {
  113.         qsort(FileNames, NumOfFiles, sizeof(FileNameType),
  114.           (int (*)(const void *, const void *)) strcmp);
  115.         if ((i = IntrQueryList("EED files", (char **) FileNames,
  116.         sizeof(FileNameType), NumOfFiles, EEListNumDisplayed,
  117.         EEPopUpFrameColor, EEPopUpBackColor, EEPopUpForeColor,
  118.         EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  119.                 INTR_WNDW_PLACE_CENTER)) < 0) {
  120.         MyFree((VoidPtr) FileNames);
  121.         return FALSE;
  122.         }
  123.         strcpy(Window -> FileName, FileNames[i]);
  124.         MyFree((VoidPtr) FileNames);
  125.         }
  126.         else {
  127.             IntrQueryContinue("No EEDraw files found.", EEPopUpFrameColor,
  128.                  EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
  129.              EEWindowsFrameWidth, &Cursor,
  130.                          INTR_WNDW_PLACE_CENTER);
  131.         return FALSE;
  132.     }
  133.     }
  134.  
  135.     if ((f = fopen(Window -> FileName, "rt")) == NULL) {
  136.     sprintf(Line, "Failed to open \"%s\"", Window -> FileName);
  137.     IntrQueryContinue(Line, EEPopUpFrameColor, EEPopUpBackColor,
  138.               EEPopUpForeColor, EEPopUpXorColor,
  139.               EEWindowsFrameWidth, &Cursor,
  140.                           INTR_WNDW_PLACE_CENTER);
  141.  
  142.     return FALSE;
  143.     }
  144.  
  145.     if (fgets(Line, LINE_LEN - 1, f) == NULL ||
  146.     strncmp(Line, EEDRAW_FILE_STAMP, sizeof(EEDRAW_FILE_STAMP) - 1) != 0) {
  147.     sprintf(Line, "\"%s\" is NOT EEDraw file", Window -> FileName);
  148.     IntrQueryContinue(Line, EEPopUpFrameColor, EEPopUpBackColor,
  149.                   EEPopUpForeColor, EEPopUpXorColor,
  150.               EEWindowsFrameWidth, &Cursor,
  151.                           INTR_WNDW_PLACE_CENTER);
  152.     fclose(f);
  153.     return FALSE;
  154.     }
  155.  
  156.     if (fgets(Line, LINE_LEN - 1, f) == NULL ||
  157.     strncmp(Line, "LIBS:", 5) != 0) {
  158.     sprintf(Line, "\"%s\" is NOT EEDraw file", Window -> FileName);
  159.     IntrQueryContinue(Line, EEPopUpFrameColor, EEPopUpBackColor,
  160.                   EEPopUpForeColor, EEPopUpXorColor,
  161.               EEWindowsFrameWidth, &Cursor,
  162.               INTR_WNDW_PLACE_CENTER);
  163.     fclose(f);
  164.     return FALSE;
  165.     }
  166.     else
  167.     LoadLibraries(&Line[5]);
  168.  
  169.     while (!feof(f) &&
  170.        fgets(Line, LINE_LEN - 1, f) != NULL) {
  171.     LineCount++;
  172.  
  173.     switch(Line[0]) {
  174.         case 'L':                      /* Its a library item. */
  175.         LibItemStruct = (DrawLibItemStruct *)
  176.                      MyMalloc(sizeof(DrawLibItemStruct));
  177.         LibItemStruct -> StructType = DRAW_LIB_ITEM_STRUCT_TYPE;
  178.         if (sscanf(&Line[1], "%s %s %s %s %d %d %d %d",
  179.                Name1, Name2,
  180.                Char1, Char2,
  181.                &LibItemStruct -> ChipNameX,
  182.                &LibItemStruct -> ChipNameY,
  183.                &LibItemStruct -> PartNameX,
  184.                &LibItemStruct -> PartNameY) != 8 ||
  185.             (Char1[0] != 'V' && Char1[0] != 'H') ||
  186.             (Char2[0] != 'V' && Char2[0] != 'H')) {
  187.             sprintf(Line,
  188.             "EEDraw file lib item struct error at line %d, aborted",
  189.                                 LineCount);
  190.             Failed = TRUE;
  191.             break;
  192.         }
  193.         LibItemStruct -> ChipNameOrient =
  194.             Char1[0] == 'V' ? TEXT_ORIENT_VERT : TEXT_ORIENT_HORIZ;
  195.         LibItemStruct -> PartNameOrient =
  196.             Char2[0] == 'V' ? TEXT_ORIENT_VERT : TEXT_ORIENT_HORIZ;
  197.  
  198.         if (strcmp(Name1, NULL_STRING) != 0) {
  199.             for (i = 0; i < strlen(Name1); i++)
  200.             if (Name1[i] == '~') Name1[i] = ' ';
  201.             LibItemStruct -> ChipName = strdup(Name1);
  202.         }
  203.         else {
  204.             LibItemStruct -> ChipName = NULL;
  205.             LibItemStruct -> ChipNameOrient = TEXT_ORIENT_NON;
  206.         }
  207.  
  208.         if (strcmp(Name2, NULL_STRING) != 0) {
  209.             for (i = 0; i < strlen(Name2); i++)
  210.             if (Name2[i] == '~') Name2[i] = ' ';
  211.             LibItemStruct -> PartName = strdup(Name2);
  212.         }
  213.         else {
  214.             LibItemStruct -> PartName = NULL;
  215.             LibItemStruct -> PartNameOrient = TEXT_ORIENT_NON;
  216.         }
  217.  
  218.         LineCount++;
  219.         if (!Failed &&
  220.             (fgets(Line, LINE_LEN - 1, f) == NULL ||
  221.              sscanf(Line, "%d %d %d %d %d %d %d",
  222.                 &LibItemStruct -> Multi,
  223.                 &LibItemStruct -> PosX,
  224.                 &LibItemStruct -> PosY,
  225.                 &LibItemStruct -> BBoxMinX,
  226.                 &LibItemStruct -> BBoxMinY,
  227.                 &LibItemStruct -> BBoxMaxX,
  228.                 &LibItemStruct -> BBoxMaxY) != 7)) {
  229.             sprintf(Line,
  230.             "EEDraw file lib item struct error at line %d, aborted",
  231.                                 LineCount);
  232.             Failed = TRUE;
  233.             break;
  234.         }
  235.  
  236.         LineCount++;
  237.         if (!Failed &&
  238.             (fgets(Line, LINE_LEN - 1, f) == NULL ||
  239.              sscanf(Line, "%d %d %d %d",
  240.                 &LibItemStruct -> Transform[0][0],
  241.                 &LibItemStruct -> Transform[0][1],
  242.                 &LibItemStruct -> Transform[1][0],
  243.                 &LibItemStruct -> Transform[1][1]) != 4)) {
  244.             sprintf(Line,
  245.             "EEDraw file lib item struct error at line %d, aborted",
  246.                                 LineCount);
  247.             Failed = TRUE;
  248.             break;
  249.         }
  250.  
  251.         if (!Failed) {
  252.             LibItemStruct -> Pnext = Window -> EEDrawList;
  253.             Window -> EEDrawList = (DrawGenericStruct *)
  254.                                             LibItemStruct;
  255.         }
  256.         break;
  257.         case 'P':                     /* Its a polyline item. */
  258.         PolylineStruct = (DrawPolylineStruct *)
  259.                     MyMalloc(sizeof(DrawPolylineStruct));
  260.         PolylineStruct -> StructType = DRAW_POLYLINE_STRUCT_TYPE;
  261.         if (sscanf(&Line[1], "%s %d",
  262.                Name1,
  263.                &PolylineStruct -> NumOfPoints) != 2 ||
  264.             (Name1[0] != 'B' && Name1[0] != 'L')) {
  265.             sprintf(Line,
  266.             "EEDraw file polyline struct error at line %d, aborted",
  267.                                 LineCount);
  268.             Failed = TRUE;
  269.             break;
  270.         }
  271.         PolylineStruct -> Width =
  272.             Name1[0] == 'B' ? GR_THICK_WIDTH : GR_NORM_WIDTH;
  273.         PolylineStruct -> Points = (int *) MyMalloc(sizeof(int) * 2 *
  274.                         PolylineStruct -> NumOfPoints);
  275.         for (i = 0; i < PolylineStruct -> NumOfPoints; i++) {
  276.             LineCount++;
  277.             if (fgets(Line, LINE_LEN - 1, f) == NULL ||
  278.             sscanf(Line, "%d %d", &PolylineStruct -> Points[i*2],
  279.                           &PolylineStruct -> Points[i*2+1])
  280.                                 != 2) {
  281.             sprintf(Line,
  282.              "EEDraw file polyline struct error at line %d, aborted",
  283.                                 LineCount);
  284.             Failed = TRUE;
  285.             MyFree((VoidPtr) PolylineStruct -> Points);
  286.             break;
  287.             }
  288.         }
  289.  
  290.         if (!Failed) {
  291.             PolylineStruct -> Pnext = Window -> EEDrawList;
  292.             Window -> EEDrawList = (DrawGenericStruct *)
  293.                                    PolylineStruct;
  294.         }
  295.         break;
  296.         case 'C':                   /* Its a connection item. */
  297.         ConnectionStruct = (DrawConnectionStruct *)
  298.                       MyMalloc(sizeof(DrawConnectionStruct));
  299.         ConnectionStruct -> StructType = DRAW_CONNECTION_STRUCT_TYPE;
  300.         if (sscanf(&Line[1], "%d %d",
  301.                &ConnectionStruct -> PosX,
  302.                &ConnectionStruct -> PosY) != 2) {
  303.             sprintf(Line,
  304.               "EEDraw file connection struct error at line %d, aborted",
  305.                                 LineCount);
  306.             Failed = TRUE;
  307.         }
  308.         else {
  309.             ConnectionStruct -> Pnext = Window -> EEDrawList;
  310.             Window -> EEDrawList = (DrawGenericStruct *)
  311.                                  ConnectionStruct;
  312.         }
  313.         break;
  314.         case 'T':                         /* Its a text item. */
  315.         TextStruct = (DrawTextStruct *)
  316.                         MyMalloc(sizeof(DrawTextStruct));
  317.         TextStruct -> StructType = DRAW_TEXT_STRUCT_TYPE;
  318.         if ((((i = sscanf(&Line[1], "%d %d %d %d",
  319.                   &TextStruct -> PosX,
  320.                   &TextStruct -> PosY,
  321.                   &TextStruct -> Orient,
  322.                   &TextStruct -> Scale)) != 3) && i != 4) ||
  323.             fgets(Line, LINE_LEN - 1, f) == NULL) {
  324.             sprintf(Line,
  325.               "EEDraw file text struct error at line %d, aborted",
  326.                                 LineCount);
  327.             Failed = TRUE;
  328.         }
  329.         else {
  330.             TextStruct -> Text = strdup(strtok(Line, "\n\r"));
  331.             TextStruct -> Pnext = Window -> EEDrawList;
  332.             Window -> EEDrawList = (DrawGenericStruct *) TextStruct;
  333.         }
  334.         if (i == 3) TextStruct -> Scale = 1;  /* No scale specified. */
  335.         break;
  336.         default:
  337.         Failed = FALSE;
  338.         sprintf(Line, "EEDraw file undef structdef at line %d, aborted",
  339.                                 LineCount);
  340.         break;
  341.     }
  342.  
  343.     if (Failed) {
  344.         IntrQueryContinue(Line, EEPopUpFrameColor, EEPopUpBackColor,
  345.                           EEPopUpForeColor, EEPopUpXorColor,
  346.                   EEWindowsFrameWidth, &Cursor,
  347.                               INTR_WNDW_PLACE_CENTER);
  348.         break;
  349.     }
  350.     }
  351.  
  352.     /* EEDrawList was constructed in reverse order - reverse it back: */
  353.     Phead = NULL;
  354.     while (Window -> EEDrawList) {
  355.     Pnext = Window -> EEDrawList;
  356.     Window -> EEDrawList = Window -> EEDrawList -> Pnext;
  357.     Pnext -> Pnext = Phead;
  358.     Phead = Pnext;
  359.     }
  360.     Window -> EEDrawList = Phead;
  361.  
  362.     fclose(f);
  363.  
  364.     return TRUE;   /* Although it may be that file is only partially loaded. */
  365. }
  366.  
  367. /*****************************************************************************
  368. * Routine to save an EEDraw file.                         *
  369. * FileSave controls how the file is to be saved - under what name.         *
  370. * Returns TRUE if the file has been saved.                     *
  371. *****************************************************************************/
  372. BooleanType SaveEEFile(FileSaveType FileSave, EEWindowStruct *Window)
  373. {
  374.     char *p, Line[LINE_LEN], Name[LINE_LEN],
  375.     Name1[LINE_LEN_SHORT], Name2[LINE_LEN_SHORT], **LibNames;
  376.     FileNameType *FileNames;
  377.     int i, NumOfFiles;
  378.     BooleanType
  379.     Failed = FALSE;
  380.     DrawGenericStruct
  381.     *Phead = Window -> EEDrawList;
  382.     DrawLibItemStruct *LibItemStruct;
  383.     DrawConnectionStruct *ConnectionStruct;
  384.     DrawPolylineStruct *PolylineStruct;
  385.     DrawTextStruct *TextStruct;
  386.     FILE *f;
  387.  
  388.     /* If no name exists in the window yet - save as new. */
  389.     if (strlen(Window -> FileName) == 0) FileSave = FILE_SAVE_NEW;
  390.  
  391.     Cursor.CursorType = INTR_CURSOR_ARROW;
  392.     switch (FileSave) {
  393.     case FILE_SAVE_AS:
  394.         sprintf(Line, "Save as \"%s\"?", Window -> FileName);
  395.         if (!IntrQueryYesNo(Line, EEPopUpFrameColor, EEPopUpBackColor,
  396.                         EEPopUpForeColor, EEPopUpXorColor,
  397.                 EEWindowsFrameWidth, &Cursor,
  398.                                 INTR_WNDW_PLACE_CENTER)) return FALSE;
  399.         strcpy(Line, Window -> FileName);
  400.  
  401.         strcpy(Name, Line);         /* Rename the old file to a '.bak' one. */
  402.         if ((p = strrchr(Name, '.')) != NULL && strlen(p) <= 4) p[0] = 0;
  403.         strcat(Name, ".bak");
  404.         unlink(Name);
  405.         rename(Line, Name);
  406.         break;
  407.     case FILE_SAVE_NEW:
  408.         strcpy(Line, FILE_EXTENSION);
  409.         IntrQueryLine("EEDraw file to save to:", Line, LINE_LEN - 1,
  410.               EEPopUpFrameColor, EEPopUpBackColor,
  411.               EEPopUpForeColor, EEWindowsFrameWidth,
  412.                           INTR_WNDW_PLACE_CENTER);
  413.         /* And make sure it has the right extension type. */
  414.         if ((p = strrchr(Line, '.')) != NULL && strlen(p) <= 4) p[0] = 0;
  415.         strcat(Line, FILE_EXTENSION);
  416.         break;
  417.     case FILE_SAVE_OLD:
  418.         sprintf(Line, "*%s", FILE_EXTENSION);
  419.         if ((FileNames = GetFileNamesDir(Line, ".", &NumOfFiles)) != NULL) {
  420.         qsort(FileNames, NumOfFiles, sizeof(FileNameType),
  421.               (int (*)(const void *, const void *)) strcmp);
  422.         if ((i = IntrQueryList("EED files", (char **) FileNames,
  423.              sizeof(FileNameType), NumOfFiles, EEListNumDisplayed,
  424.              EEPopUpFrameColor, EEPopUpBackColor, EEPopUpForeColor,
  425.              EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  426.              INTR_WNDW_PLACE_CENTER)) < 0) {
  427.             MyFree((VoidPtr) FileNames);
  428.             return FALSE;
  429.         }
  430.         strcpy(Line, FileNames[i]);
  431.         MyFree((VoidPtr) FileNames);
  432.         }
  433.         else {
  434.         IntrQueryContinue("No EEDraw files found.",
  435.                           EEPopUpFrameColor, EEPopUpBackColor,
  436.                   EEPopUpForeColor, EEPopUpXorColor,
  437.                   EEWindowsFrameWidth, &Cursor,
  438.                                   INTR_WNDW_PLACE_CENTER);
  439.         return FALSE;
  440.         }
  441.  
  442.         sprintf(Name, "Save as \"%s\"?", Line);
  443.         if (!IntrQueryYesNo(Name, EEPopUpFrameColor, EEPopUpBackColor,
  444.                         EEPopUpForeColor, EEPopUpXorColor,
  445.                 EEWindowsFrameWidth, &Cursor,
  446.                                 INTR_WNDW_PLACE_CENTER)) return FALSE;
  447.  
  448.         strcpy(Name, Line);         /* Rename the old file to a '.bak' one. */
  449.         if ((p = strrchr(Name, '.')) != NULL && strlen(p) <= 4) p[0] = 0;
  450.         strcat(Name, ".bak");
  451.         unlink(Name);
  452.         rename(Line, Name);
  453.         break;
  454.     }
  455.  
  456.     if ((f = fopen(Line, "wt")) == NULL) {
  457.     IntrQueryContinue("Failed to open file",
  458.               EEPopUpFrameColor, EEPopUpBackColor,
  459.               EEPopUpForeColor, EEPopUpXorColor,
  460.               EEWindowsFrameWidth, &Cursor,
  461.               INTR_WNDW_PLACE_CENTER);
  462.     return FALSE;
  463.     }
  464.  
  465.     LibNames = GetLibNames();
  466.     for (i = 0, Name[0] = 0; LibNames[i] != NULL; i++) {
  467.     if (i > 0) strcat(Name, ",");
  468.     strcat(Name, LibNames[i]);
  469.     }
  470.     MyFree((VoidPtr) LibNames);
  471.  
  472.     if (fprintf(f, "%s EEDRAW PROGRAM %s\n",
  473.         EEDRAW_FILE_STAMP, EEDRAW_VERSION) == EOF ||
  474.     fprintf(f, "LIBS:%s\n", Name) == EOF) {
  475.     IntrQueryContinue("File write operation failed.",
  476.               EEPopUpFrameColor, EEPopUpBackColor,
  477.               EEPopUpForeColor, EEPopUpXorColor,
  478.               EEWindowsFrameWidth, &Cursor,
  479.                           INTR_WNDW_PLACE_CENTER);
  480.     fclose(f);
  481.     return FALSE;
  482.     }
  483.  
  484.     while (Phead) {
  485.     switch(Phead -> StructType) {
  486.         case DRAW_LIB_ITEM_STRUCT_TYPE:          /* Its a library item. */
  487.         LibItemStruct = (DrawLibItemStruct *) Phead;
  488.  
  489.         if (LibItemStruct -> PartName != NULL) {
  490.             strcpy(Name1, LibItemStruct -> PartName);
  491.             for (i = 0; i < strlen(Name1); i++)
  492.             if (Name1[i] <= ' ') Name1[i] = '~';
  493.         }
  494.         else
  495.             strcpy(Name1, NULL_STRING);
  496.         if (LibItemStruct -> ChipName != NULL) {
  497.             strcpy(Name2, LibItemStruct -> ChipName);
  498.             for (i = 0; i < strlen(Name2); i++)
  499.             if (Name2[i] <= ' ') Name2[i] = '~';
  500.         }
  501.         else
  502.             strcpy(Name2, NULL_STRING);
  503.  
  504.         if (fprintf(f, "L %-10s %-10s %c %c %-3d %-3d %-3d %-3d\n",
  505.             Name2, Name1,
  506.             LibItemStruct -> ChipNameOrient == TEXT_ORIENT_VERT ? 'V' : 'H',
  507.             LibItemStruct -> PartNameOrient == TEXT_ORIENT_VERT ? 'V' : 'H',
  508.             LibItemStruct -> ChipNameX,
  509.             LibItemStruct -> ChipNameY,
  510.             LibItemStruct -> PartNameX,
  511.             LibItemStruct -> PartNameY) == EOF) {
  512.             Failed = TRUE;
  513.             break;
  514.         }
  515.  
  516.         if (!Failed &&
  517.             fprintf(f, "\t%-4d %-4d %-4d %-4d %-4d %-4d %-4d\n",
  518.                 LibItemStruct -> Multi,
  519.                 LibItemStruct -> PosX,
  520.                 LibItemStruct -> PosY,
  521.                 LibItemStruct -> BBoxMinX,
  522.                 LibItemStruct -> BBoxMinY,
  523.                 LibItemStruct -> BBoxMaxX,
  524.                 LibItemStruct -> BBoxMaxY) == EOF) {
  525.             Failed = TRUE;
  526.             break;
  527.         }
  528.  
  529.         if (!Failed &&
  530.             fprintf(f, "\t%-4d %-4d %-4d %-4d\n",
  531.                 LibItemStruct -> Transform[0][0],
  532.                 LibItemStruct -> Transform[0][1],
  533.                 LibItemStruct -> Transform[1][0],
  534.                 LibItemStruct -> Transform[1][1]) == EOF) {
  535.             Failed = TRUE;
  536.             break;
  537.         }
  538.         break;
  539.         case DRAW_POLYLINE_STRUCT_TYPE:         /* Its a polyline item. */
  540.         PolylineStruct = (DrawPolylineStruct *) Phead;
  541.         if (fprintf(f, "P %c %d\n",
  542.             PolylineStruct -> Width == GR_NORM_WIDTH ? 'L' : 'B',
  543.             PolylineStruct -> NumOfPoints) == EOF) {
  544.             Failed = TRUE;
  545.             break;
  546.         }
  547.         for (i = 0; i < PolylineStruct -> NumOfPoints; i++) {
  548.             if (fprintf(f, "\t%-4d %-4d\n",
  549.             PolylineStruct -> Points[i*2],
  550.             PolylineStruct -> Points[i*2+1]) == EOF) {
  551.             Failed = TRUE;
  552.             break;
  553.             }
  554.         }
  555.         break;
  556.         case DRAW_CONNECTION_STRUCT_TYPE:       /* Its a connection item. */
  557.         ConnectionStruct = (DrawConnectionStruct *) Phead;
  558.         if (fprintf(f, "C %-4d %-4d\n",
  559.             ConnectionStruct -> PosX,
  560.             ConnectionStruct -> PosY) == EOF) {
  561.             Failed = TRUE;
  562.         }
  563.         break;
  564.         case DRAW_TEXT_STRUCT_TYPE:             /* Its a text item. */
  565.         TextStruct = (DrawTextStruct *) Phead;
  566.         if (TextStruct -> Scale > 1) {
  567.             if (fprintf(f, "T %-4d %-4d %-4d %-4d\n%s\n",
  568.                 TextStruct -> PosX,
  569.                 TextStruct -> PosY,
  570.                 TextStruct -> Orient,
  571.                 TextStruct -> Scale,
  572.                 TextStruct -> Text) == EOF)
  573.             Failed = TRUE;
  574.         }
  575.         else {
  576.             if (fprintf(f, "T %-4d %-4d %-4d\n%s\n",
  577.                 TextStruct -> PosX,
  578.                 TextStruct -> PosY,
  579.                 TextStruct -> Orient,
  580.                 TextStruct -> Text) == EOF)
  581.             Failed = TRUE;
  582.         }
  583.         break;
  584.     }
  585.  
  586.     if (Failed) {
  587.         IntrQueryContinue("File write operation failed.",
  588.                   EEPopUpFrameColor, EEPopUpBackColor,
  589.                   EEPopUpForeColor, EEPopUpXorColor,
  590.                   EEWindowsFrameWidth, &Cursor,
  591.                   INTR_WNDW_PLACE_CENTER);
  592.         break;
  593.     }
  594.  
  595.     Phead = Phead -> Pnext;
  596.     }
  597.     fclose(f);
  598.  
  599.     if (FileSave == FILE_SAVE_NEW)
  600.     strcpy(Window -> FileName, Line);
  601.  
  602.     return !Failed;
  603. }
  604.  
  605. /*****************************************************************************
  606. * Routine to save a net list of the given EEDraw window (file).             *
  607. *****************************************************************************/
  608. void SaveNetList(EEWindowStruct *Window)
  609. {
  610.     FILE *f;
  611.     int PercentDone, i, j,
  612.     NumOfPolylines = 0;
  613.     BooleanType IsABus;
  614.     char **StrVec, *Str, Line[LINE_LEN], SLine[LINE_LEN_SHORT];
  615.     DrawGenericStruct *p,
  616.     *Phead = Window -> EEDrawList;
  617.     NetListStruct *NetList, *NetListHead;
  618.     DrawPolylineStruct *PolylineStruct;
  619.  
  620.     /* Make sure this window is on top since we are going to draw to it. */
  621.     IntrWndwPop(Window -> IntrLibWindowID, TRUE, FALSE);
  622.  
  623.     strcpy(Line, Window -> FileName);
  624.     if ((Str = strrchr(Line, '.')) != NULL && strlen(Str) < 5) Str[0] = 0;
  625.     strcat(Line, NETLIST_FILE_EXTENSION);
  626.  
  627.     IntrQueryLine("File name to save NET LIST:", Line, LINE_LEN - 1,
  628.           EEPopUpFrameColor, EEPopUpBackColor, EEPopUpForeColor,
  629.           EEWindowsFrameWidth, INTR_WNDW_PLACE_CENTER);
  630.  
  631.     if ((f = fopen(Line, "wt")) == NULL) {
  632.     IntrQueryContinue("Failed to open file",
  633.               EEPopUpFrameColor, EEPopUpBackColor,
  634.               EEPopUpForeColor, EEPopUpXorColor,
  635.               EEWindowsFrameWidth, &Cursor,
  636.               INTR_WNDW_PLACE_CENTER);
  637.     return;
  638.     }
  639.  
  640.     /* Mark all polylines as untested at first path. */
  641.     for (p = Phead; p != NULL; p = p -> Pnext) {
  642.     switch(p -> StructType) {
  643.         case DRAW_POLYLINE_STRUCT_TYPE:         /* Its a polyline item. */
  644.         NumOfPolylines++;
  645.         PolylineStruct = (DrawPolylineStruct *) p;
  646.         PolylineStruct -> Flags = FALSE;
  647.         break;
  648.     }
  649.     }
  650.  
  651.     GlblNumOfPolylines = NumOfPolylines;
  652.  
  653.     sprintf(SLine, "Net List - %d%% done.", 0);
  654.     IntrDrawMessage(SLine, EEPopUpForeColor, EEPopUpBackColor);
  655.     PercentDone = 0;
  656.  
  657.     /* Second path - scan for all polylines and for each untested polyline   */
  658.     /* get its net list and dump it out to the open file.             */
  659.     for (p = Phead; p != NULL; p = p -> Pnext) {
  660.     switch(p -> StructType) {
  661.         case DRAW_POLYLINE_STRUCT_TYPE:         /* Its a polyline item. */
  662.         i = (100 * (NumOfPolylines - GlblNumOfPolylines)) /
  663.                                   NumOfPolylines;
  664.         if (i != PercentDone) {
  665.             IntrEraseMessage();
  666.             sprintf(SLine, "Net List - %d%% done.", i);
  667.             PercentDone = i;
  668.             IntrDrawMessage(SLine, EEPopUpForeColor, EEPopUpBackColor);
  669.         }
  670.  
  671.         PolylineStruct = (DrawPolylineStruct *) p;
  672.         if (!PolylineStruct -> Flags) {
  673.             /* We have not visited this polyline - do it now. */
  674.             IsABus = FALSE;
  675.             NetListHead = NULL;
  676.             GetPolylineNetList(PolylineStruct, Phead, &NetListHead,
  677.                                     &IsABus);
  678.  
  679.             /* Print the net list into the file. */
  680.             if (NetListHead != NULL) {
  681.             for (NetList = NetListHead, i = 0;
  682.                  NetList != NULL;
  683.                  NetList = NetList -> Pnext, i++);
  684.             if (i > 0) {
  685.                 /* Sort entries in lexicographic order. */
  686.                 StrVec = (char **) MyMalloc(sizeof(char *) * i);
  687.                 for (NetList = NetListHead, j = 0;
  688.                  NetList != NULL;
  689.                  NetList = NetList -> Pnext, j++)
  690.                 StrVec[j] = NetList -> Pin;
  691.                 qsort(StrVec, i, sizeof(char *), StringComp);
  692.  
  693.                 /* Print the sorted list. */
  694.                 fprintf(f, "\nConnection:\n");
  695.                 for (j = 0; j < i; j++)
  696.                 fprintf(f, "\t%s\n", StrVec[j]);
  697.                 fprintf(f, "End Connection%s.\n",
  698.                     IsABus ? " (BUS)" : "");
  699.                 MyFree(StrVec);
  700.             }
  701.  
  702.             /* And delete the memory. */
  703.             while (NetListHead != NULL) {
  704.                 NetList = NetListHead -> Pnext;
  705.                 MyFree(NetListHead);
  706.                 NetListHead = NetList;
  707.             }
  708.             }
  709.         }
  710.         break;
  711.     }
  712.     }
  713.     IntrEraseMessage();
  714.  
  715.     fclose(f);
  716. }
  717.  
  718. /*****************************************************************************
  719. * Simple wrapper for strcmp so qsort above can call it on char ** type.      *
  720. *****************************************************************************/
  721. static int StringComp(const void *Str1, const void *Str2)
  722. {
  723.     return strcmp(*((char **) Str1), *((char **) Str2));
  724. }
  725.  
  726. /*****************************************************************************
  727. * Routine to search and find all library items intersecting with this line   *
  728. * since other lines may intersect with it other lines are scaned as well.    *
  729. *****************************************************************************/
  730. static void GetPolylineNetList(DrawPolylineStruct *PolylineStruct,
  731.                    DrawGenericStruct *Phead,
  732.                    NetListStruct **NetListHead,
  733.                    BooleanType *IsABus)
  734. {
  735.     int i, j, *OPoints, ONumPts, l1x1, l1y1, l1x2, l1y2,
  736.     *Points = PolylineStruct -> Points,
  737.     NumPts = PolylineStruct -> NumOfPoints;
  738.     BooleanType LinesInter;
  739.     DrawGenericStruct *p;
  740.     DrawPolylineStruct *OPolylineStruct;
  741.  
  742.     PolylineStruct -> Flags = TRUE;           /* We visited this polyline... */
  743.     RedrawOneStruct((DrawGenericStruct *) PolylineStruct,
  744.             GR_COPY_PUT, EE_HIGHLIGHT_COLOR);
  745.     GRSetLineStyle(GR_SOLID_LINE, 0, GR_NORM_WIDTH);
  746.  
  747.     /* Generate the netlist for this polyline */
  748.     GetOnePolylineNetList(PolylineStruct, Phead, NetListHead, IsABus);
  749.  
  750.     /* And scan for other polylines intersecting this one: */
  751.     for (p = Phead; p != NULL; p = p -> Pnext) {
  752.     switch(p -> StructType) {
  753.         case DRAW_POLYLINE_STRUCT_TYPE:         /* Its a polyline item. */
  754.         OPolylineStruct = (DrawPolylineStruct *) p;
  755.         if (!OPolylineStruct -> Flags) {
  756.             /* Found an untested polyline - do the intersect? */
  757.             OPoints = OPolylineStruct -> Points;
  758.             ONumPts = OPolylineStruct -> NumOfPoints;
  759.             LinesInter = FALSE;
  760.             for (i = 0; i < NumPts - 1 && !LinesInter; i++) {
  761.             l1x1 = Points[i * 2];
  762.             l1y1 = Points[i * 2 + 1];
  763.             l1x2 = Points[i * 2 + 2];
  764.             l1y2 = Points[i * 2 + 3];
  765.  
  766.             for (j = 0; j < ONumPts - 1 && !LinesInter; j++) {
  767.                 LinesInter = LinesIntersect(
  768.                 l1x1, l1y1,
  769.                 l1x2, l1y2,
  770.                 OPoints[j * 2], OPoints[j * 2 + 1],
  771.                 OPoints[j * 2 + 2], OPoints[j * 2 + 3],
  772.                 PolylineStruct -> Width == GR_THICK_WIDTH,
  773.                 OPolylineStruct -> Width == GR_THICK_WIDTH,
  774.                 Phead);
  775.             }
  776.             }
  777.  
  778.             if (LinesInter)
  779.             GetPolylineNetList(OPolylineStruct, Phead,
  780.                        NetListHead, IsABus);
  781.         }
  782.         break;
  783.     }
  784.     }
  785. }
  786.  
  787. /*****************************************************************************
  788. * Routine to search and find all library items intersecting with this line.  *
  789. *****************************************************************************/
  790. static void GetOnePolylineNetList(DrawPolylineStruct *PolylineStruct,
  791.                   DrawGenericStruct *Phead,
  792.                   NetListStruct **NetListHead,
  793.                   BooleanType *IsABus)
  794. {
  795.     int i,
  796.     *Points = PolylineStruct -> Points,
  797.     NumPts = PolylineStruct -> NumOfPoints;
  798.     BooleanType
  799.     PolyIsABus = PolylineStruct -> Width == GR_THICK_WIDTH;
  800.     NetListStruct *NewNetList, *NetListItem, *NetListNext;
  801.     DrawLibItemStruct *LibItemStruct;
  802.     DrawGenericStruct *p;
  803.  
  804.     if (PolyIsABus) *IsABus = TRUE;
  805.  
  806.     for (p = Phead; p != NULL; p = p -> Pnext) {
  807.     switch(p -> StructType) {
  808.         case DRAW_LIB_ITEM_STRUCT_TYPE:          /* Its a library item. */
  809.         LibItemStruct = (DrawLibItemStruct *) p;
  810.         for (i = 0; i < NumPts - 1; i++) {
  811.             NewNetList = FindLibItemNetList(
  812.                 Points[i * 2], Points[i * 2 + 1],
  813.                 Points[i * 2 + 2], Points[i * 2 + 3],
  814.                 PolyIsABus, Phead, LibItemStruct);
  815.             while (NewNetList) {
  816.             /* Linear search old pins to see if we have it: */
  817.             for (NetListItem = *NetListHead;
  818.                  NetListItem != NULL;
  819.                  NetListItem = NetListItem -> Pnext)
  820.                 if (strcmp(NetListItem -> Pin,
  821.                        NewNetList -> Pin) == 0) break;
  822.  
  823.             NetListNext = NewNetList -> Pnext;
  824.             if (NetListItem != NULL) {
  825.                 /* We already have it - delete the new one. */
  826.                 MyFree(NewNetList);
  827.             }
  828.             else {
  829.                 /* Its new - add the net list result list. */
  830.                 NewNetList -> Pnext = *NetListHead;
  831.                 *NetListHead = NewNetList;
  832.             }
  833.             NewNetList = NetListNext;
  834.             }
  835.         }
  836.     }
  837.     }
  838.  
  839.     GlblNumOfPolylines--;
  840. }
  841.  
  842. /*****************************************************************************
  843. * Returns TRUE iff l1 intersects l2. Both line segments are given by thier   *
  844. * end points and assumed to be horizontal or vertical only.             *
  845. *****************************************************************************/
  846. BooleanType LinesIntersect(int l1x1, int l1y1, int l1x2, int l1y2,
  847.                int l2x1, int l2y1, int l2x2, int l2y2,
  848.                BooleanType l1Bus, BooleanType l2Bus,
  849.                DrawGenericStruct *Phead)
  850. {
  851.     int l1xmin, l1xmax, l1ymin, l1ymax, l2xmin, l2xmax, l2ymin, l2ymax;
  852.  
  853.     /* Eliminate the common case of intersecting at the end points. */
  854.     if ((l1x1 == l2x1 && l1y1 == l2y1) ||
  855.     (l1x1 == l2x2 && l1y1 == l2y2) ||
  856.     (l1x2 == l2x1 && l1y2 == l2y1) ||
  857.     (l1x2 == l2x2 && l1y2 == l2y2)) return TRUE;
  858.  
  859.     if (l1x1 == l1x2) {                         /* Line l1 is vertical. */
  860.     l1ymin = MIN(l1y1, l1y2);
  861.     l1ymax = MAX(l1y1, l1y2);
  862.  
  863.     if (l2x1 == l2x2) {                 /* Line l2 is vertical. */
  864.         if (l1x1 != l2x1) return FALSE;   /* Both vertical with diff. x. */
  865.  
  866.         l2ymin = MIN(l2y1, l2y2);
  867.         l2ymax = MAX(l2y1, l2y2);
  868.  
  869.         return MIN(l1ymax, l2ymax) >= MAX(l1ymin, l2ymin);
  870.     }
  871.     else {                       /* Line l2 is horizontal. */
  872.         l2xmin = MIN(l2x1, l2x2);
  873.         l2xmax = MAX(l2x1, l2x2);
  874.  
  875.         if ((l2y1 >= l1ymin && l2y1 <= l1ymax &&
  876.          (l1x1 == l2x1 || l1x1 == l2x2)) ||
  877.         (l2xmin <= l1x1 && l2xmax >= l1x1 &&
  878.          (l1y1 == l2y1 || l1y2 == l2y1))) {
  879.         /* One line ends on the other middle. Returns TRUE if one of */
  880.         /* the lines is a BUS or a connection exists at that point.  */
  881.         return l1Bus || l2Bus ||
  882.                ConnectionExistsAtXY(Phead, l1x1, l2y1);
  883.         }
  884.         else if (l2xmin <= l1x1 && l2xmax >= l1x1 &&
  885.              l2y1 >= l1ymin && l2y1 <= l1ymax) {
  886.         /* They intersect. Test if exists a connection at that point */
  887.         /* and return TRUE iff such connection exist.             */
  888.         /* Also accept it as intersection if one of lines is a bus.  */
  889.         return ConnectionExistsAtXY(Phead, l1x1, l2y1);
  890.         }
  891.         else
  892.         return FALSE;
  893.     }
  894.     }
  895.     else {                           /* Line l1 is horizontal. */
  896.     l1xmin = MIN(l1x1, l1x2);
  897.     l1xmax = MAX(l1x1, l1x2);
  898.  
  899.     if (l2x1 == l2x2) {                 /* Line l2 is vertical. */
  900.         l2ymin = MIN(l2y1, l2y2);
  901.         l2ymax = MAX(l2y1, l2y2);
  902.  
  903.         if ((l2x1 >= l1xmin && l2x1 <= l1xmax &&
  904.          (l1y1 == l2y1 || l1y1 == l2y2)) ||
  905.         (l2ymin <= l1y1 && l2ymax >= l1y1 &&
  906.          (l1x1 == l2x1 || l1x2 == l2x1))) {
  907.         /* One line ends on the other middle. Returns TRUE if one of */
  908.         /* the lines is a BUS or a connection exists at that point.  */
  909.         return l1Bus || l2Bus ||
  910.                ConnectionExistsAtXY(Phead, l2x1, l1y1);
  911.         }
  912.         else if (l2ymin <= l1y1 && l2ymax >= l1y1 &&
  913.              l2x1 >= l1xmin && l2x1 <= l1xmax) {
  914.         /* They intersect. Test if exists a connection at that point */
  915.         /* and return TRUE iff such connection exist.             */
  916.         /* Also accept it as intersection if one of lines is a bus.  */
  917.         return ConnectionExistsAtXY(Phead, l2x1, l1y1);
  918.         }
  919.         else
  920.         return FALSE;
  921.     }
  922.     else {                       /* Line l2 is horizontal. */
  923.         if (l1y1 != l2y1) return FALSE; /* Both horizontal with diff. y. */
  924.  
  925.         l2xmin = MIN(l2x1, l2x2);
  926.         l2xmax = MAX(l2x1, l2x2);
  927.  
  928.         return MIN(l1xmax, l2xmax) >= MAX(l1xmin, l2xmin);
  929.     }
  930.     }
  931. }
  932.  
  933. /*****************************************************************************
  934. * Scans the given drawing object list for connection position at X Y and     *
  935. * returns TRUE iff such connection is found.                     *
  936. *****************************************************************************/
  937. static BooleanType ConnectionExistsAtXY(DrawGenericStruct *Phead, int x, int y)
  938. {
  939.     DrawConnectionStruct *ConnectionStruct;
  940.  
  941.     while (Phead) {
  942.     switch(Phead -> StructType) {
  943.         case DRAW_CONNECTION_STRUCT_TYPE:       /* Its a connection item. */
  944.         ConnectionStruct = (DrawConnectionStruct *) Phead;
  945.         if (ABS(x - ConnectionStruct -> PosX) < EESnapDistance &&
  946.             ABS(y - ConnectionStruct -> PosY) < EESnapDistance)
  947.             return TRUE;
  948.         break;
  949.     }
  950.  
  951.     Phead = Phead -> Pnext;
  952.     }
  953.  
  954.     return FALSE;
  955. }
  956.  
  957.