#usage "en: <qt>This ULP generates the CONNECT list for a new Device<p></nobr>"
       "that consists of several Symbols (Gates), "
       "which have been extracted from one big Symbol by GROUP CUT and PASTE.<p> "
       "Example:<br> "
       "It is possible to generate a Device with Symbol and Package from a BSDL or a text file (spreadsheet) with "
       "the help of <i>RUN make-symbol-device-package-bsdl</i>. In the case the Symbol becomes too big and does not "
       "fit onto a single schematic sheet due to the number of pins, you can divide it into several smaller Symbols with "
       "the commands GROUP, CUT, EDIT xx.sym, PASTE and so on. With the help of this ULP you can adopt the Connect "
       "list from the 'original Device'.<p> "
       "Please note:<br> "
       "There must not be pins with same names. So it is not possible to use this ULP for Devices that consist of "
       "several identical Symbols (gates like NAND or OP-AMP..).<br> "
       "The chosen Package variant will be generated in the current Device. If this variant already exists, the "
       "Connect list will be checked. If there are already connects between pins and pads, the ULP exits with an error message. "
       "<p>"
       "<author>librarian@cadsoft.de</author></qt>"
       ,
       "de: <qt><nobr>Dieses ULP erstellt die CONNECT-Liste für ein neues Device<p></nobr>"
       "das aus mehreren Symbolen (Gates) besteht, "
       "die wiederum durch GROUP CUT und PASTE aus einem großen Symbol erstellt wurden.<p>"
       "Beispiel:<br>"
       "Mit <i>RUN make-symbol-device-package-bsdl</i> kann mit einer BSDL- oder Textdatei (Tabelle) ein Device mit Symbol "
       "und Package generiert werden. In den Fällen, in denen das Symbol durch die Anzahl der Pins zu groß wird, "
       "um es im Schaltplan auf eine Seite zu platzieren kann mit GROUP - CUT - EDIT xx.sym - PASTE .... das Symbol in "
       "mehrere kleinere Symbole aufgeteilt werden und mit Hilfe dieses ULPs die Connect-Liste vom 'Original-Device' übernommen werden.<p>"
       "ACHTUNG:<br>"
       "Es dürfen keine Pin-Namen doppelt vorkommen. So ist es z.B. nicht möglich dieses ULP für ein Device, das aus mehreren gleichen "
       "Symbolen (Gates wie NAND oder OP-AMP) besteht, zu benutzen.<br>"
       "Die gewählte Package-Variante wird im aktuellen Device erzeugt. Sollte die Variante schon vorhanden sein "
       "wird die Connect-Liste überprüft. Sind Connects zwischen Pins und Pads vorhanden, so wird das ULP mit einer Fehlernummer beendet."
       "<p>"
       "<author>librarian@cadsoft.de</author></qt>"



string Version = "1.02";  // 1.00 - 2006.12.01 alf@cadsoft.de
                          // 1.01 - 2007.08.07 Abfrage der selektierten Variante darf nicht negativ sein.
                          //                   überprüft die Connectliste falls die Package-Variate schon angelegt ist
                          // 1.02 - 2008.04.24 Hinweis zum selektieren durch doppelklick

string listv1 = "Select a &Device to get Connect list";
string listv2 = "Select a Package &Variant";
string listv3 = "<font color= \"red\">double click in list</font>";
string listv4 = " ";

if (language() == "de") {
  listv1 = "Wählen Sie ein &Device für die Connectliste";
  listv2 = "Wählen Sie eine Package &Variante";
  listv3 = "<font color= \"red\">doppelklick in Liste</font>";
  listv4 = " ";
}

string DeviceVariant, Pin_Name[], Pad_Name[];
string DeviceSet;
string Device_Sets[];
string Variant[];
string Package[];
string Device_Variant[], Device_Package[];
int    cntD = 0;
int    cntConnect = 0;

string actualpackage = " ";

string cmd;
string DeviceDescription;

string replacenewline(string nl) {
  string a[];
  int n = strsplit(a, nl, '\n');
  if (n > 0) {
    nl = "";
    for (int x = 0; x < n - 1; x++) {
      nl += a[x] + "\\n";
    }
    nl += a[x];
  }
  return "'" + nl + "'";
}


string checkVariant(string s) {
  if (s == "''") s = "''''";
  return s;
}


void getPackage(int x) {
  actualpackage = Device_Package[x]+".PAC";
  return;
}


void getVariant(int x) {
  string p[], v[];
  int cnt;
  cnt = strsplit(p, Package[x], ' ');
  cnt = strsplit(v, Variant[x], ' ');
  for (int n = 0; n < cnt; n++) {
    Device_Variant[n] = v[n];
    Device_Package[n] = p[n];
  }
  return;
}


string getPadName(string name) {
  for (int n = 0; n < cntConnect; n++) {
    if (name == Pin_Name[n]) return Pad_Name[n];
  }
  return "";
}


if (library) {
  string file;
  if (deviceset) {
    deviceset(DEV) {
      DeviceSet = DEV.name;
      DEV.devices(D) {
        cntConnect = 0;
        D.gates(G) {
          G.symbol.pins(P) {
            cntConnect++;                  // count all pins
          }
        }
      }
    }
    if (!cntConnect) {
      if (language() == "de") {
        dlgMessageBox("!Dieses Deviceset besitzt kein(e) Symbol(e)", "OK");
      }
      else {
        dlgMessageBox("!This Device set has no Symbol(s)", "OK");
      }
      exit(0);
    }

    int selD = -1;
    int selV = -1;
    library(L) {
      L.devicesets(DEV) {    // collect only devicesets with the same counts of connects as the actual deviceset
        int cntC;
        if (DEV.name != DeviceSet) {
          DEV.devices(D) {
            cntC = 0;
            D.gates(G) {
              G.symbol.pins(P) cntC++;
            }
            if (cntC == cntConnect) {
              Device_Sets[cntD] = DEV.name;
              Variant[cntD] += D.name + " ";   // Package Variant
              Package[cntD] += D.package.name + " ";
            }
            else {
// only for test / nur zum test
// sprintf(cmd , "%d Connects in %s : %d connects in %s", cntC, DEV.name, cntConnect, DeviceSet);
// if (dlgMessageBox(cmd, "OK", "esc") != 0) exit(-99);
            }
          }
          if (cntC == cntConnect) cntD++;
        }
      }
      string use_Device;
      int listsel = 0;
      string infodev;
      sprintf(infodev, "%d Devivces found with %d connects", cntD, cntConnect);
      do {
        int RESULT = dlgDialog(filename(argv[0])) {
          dlgHBoxLayout {
            dlgLabel(DeviceSet+".DEV");
            //dlgLabel(" Variant:"+DeviceVariant);
          }
          dlgSpacing(8);

          dlgHBoxLayout {
            dlgGridLayout {
              dlgCell(0,  1) dlgLabel(listv1);
              dlgCell(1,  1) dlgListView("Device", Device_Sets, selD, listsel) {
                               getVariant(selD); actualpackage = " ";
                               if (language() == "de") actualpackage = "<font color= \"red\">doppelklick in Liste</font>";
                               else actualpackage = "<font color= \"red\">double click in list</font>";
                               listv3 = " ";
                             }
              dlgCell(0,  2) dlgSpacing(12);
              dlgCell(0,  3) dlgLabel("Select a Package &Variant") ;
              dlgCell(1,  3) dlgListView("Variant", Device_Variant, selV) getPackage(selV);
              dlgCell(2,  1) dlgLabel(listv3, 1);
              dlgCell(2,  3) dlgLabel(actualpackage, 1);
            }
            dlgStretch(1);
          }
          dlgLabel(infodev);
          dlgHBoxLayout {
            dlgPushButton("+OK") dlgAccept();
            dlgPushButton("-Cancel") dlgReject();
            dlgPushButton("&Help") dlgMessageBox(usage);
          }
        };
        if (!RESULT) exit(0);

        if (selD < 0) {
          if (language() == "de") {
            dlgMessageBox("Kein DEVICE gewählt!", "OK");
          }
          else {
            dlgMessageBox("No DEVICE selected!", "OK");
          }
        }
        else {
          // 2007.08.03
          if (selV < 0) {
            if (language() == "de") {
              dlgMessageBox("!Keine Variante gewählt.\nWählen Sie eine Variante.\nDurch doppelklick auf das Device wird die Spalte Variant angezeigt.", "OK");
            }
            else {
              dlgMessageBox("No package variant selected!\nTo display the variant colomn, select a Device with a double mouse click first.", "OK");
            }
          }
        }
      } while (selD < 0 || selV < 0);
    }
    library(L) {
      file = filesetext(L.name, "~connect.scr");
      L.devicesets(DEV) {
        if (DEV.name == Device_Sets[selD]) {
          DEV.devices(D) {
            if (D.name == Device_Variant[selV]) {
              int n = 0;
              D.gates(G) {
                G.symbol.pins(P) {
                  Pin_Name[n] = P.name;
                  Pad_Name[n] = P.contact.name;
                  n++;
                }
              }
            }
          }
          DeviceDescription = DEV.description;
        }
      }
    }
    deviceset(DEV) {
      int variant_not_used = 1;
      int variant_exist = 0;
      DEV.devices(D) {
        if (D.name == Device_Variant[selV]) {
          if (D.package) {         // 2007.08.06
            variant_exist = 1;
            D.gates(G) {
              G.symbol.pins(P) {
                if (P.contact) {
                  variant_not_used = 0;
                  break;
                }
              }
            }
          }

          if (variant_not_used == 0) {
            string h;
            if (language() == "de") {
              sprintf(h, "<nobr>Package-Variante <b>%s</b><br>schon vorhanden und connected.<br>Benutzen Sie eine noch nicht vorhandene Variante in der Quelle,</nobr> oder löschen Sie die Variante im aktuellen Device!", D.name);
            }
            else {
              sprintf(h, "<nobr>Package-Variant <b>%s</b><br>is already defined and connected.<br>Choose a a new variant in the source or delete this variant in the current Device.", D.name);
            }
            dlgMessageBox(h, "OK");
            exit(-1);
          }
        }
      }
      if (variant_not_used) {
        output(file, "wtD") {
          DEV.devices(D) {
            if (!variant_exist) printf("PACKAGE %s %s;\n", Device_Package[selV], Device_Variant[selV]);
            D.gates(G) {
              G.symbol.pins(P) {
                string pad = getPadName(P.name);
                if (language() == "de") {
                  if (!pad) dlgMessageBox("Kein PAD gefunden für "+ P.name +"\nÜberprüfen Sie die Pinnamen der Symbole", "OK");
                }
                else {
                  if (!pad) dlgMessageBox("No PAD found for "+ P.name +"\nCheck the Pin names of the Symbols", "OK");
                }
                printf("CONNECT '%s.%s' '%s';\n", G.name, P.name, pad);   // 2007.08.6 *** Namen in ' ' wegen Kommentarzeichen in Scripten "#"
              }
            }
            string t[];
            printf("DESCRIPTION %s;\n", replacenewline(DeviceDescription+"<br><i>Connect-List generated from </i><b>"+ Device_Sets[selD] +".DEV</b> Variant <b>"+ checkVariant(Device_Variant[selV]) +"</b> with <i><b>"+ filename(argv[0])+"</b></i>"));
          }
          printf("WIN FIT;\n");
        }
        exit("SCRIPT '"+ file + "';\n");
      }
    }
  }
  else {
    if (language() == "de") {
      dlgMessageBox("Öffnen Sie ein Device.", "OK");
    }
    else {
      dlgMessageBox("Edit a Device.", "OK");
    }
  }
}

else dlgMessageBox("Start this ULP in a LBR (Device)", "OK");
