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