#usage "Create library or libraries from schematic/board

\n" "Can be used to make individual changes to components in a project. " "Just load the schematic, use this ULP to generate a library or several libraries " "containing the used components, make you changes in the library, and use the " "UPDATE command to introduce the changes to the schematic or board.

" "See Help for further details

" "Author: support@cadsoft.de" string PrevName = ""; string x[]; string CurrentLbrName = ""; string EditName; string h, cmd = "", logf = ""; string ScriptName, PureScriptName; string LogName, PureLogName; string WorkPath; string Status = ""; int n; int NameIndex = 0; int IsPackage = 1; int onelib = 0, show_script = 0, save_log = 1, multiple_symbols = 1; string HelpText = "Create project library from schematic or board

\n" "This program collects the parts from a schematic or board and stores them back " "into one or several libraries.

\n" "Attention: Before using this program please make sure no library is open and that all layers containing objects " "are used. If in doubt, execute the command
\n" "   SET USED_LAYERS ALL

\n" "If parts coming from old libraries contain objects in forbidden layers, these objects are moved " "automatically to new layers and it is reported in the log file.

\n" "Creation Mode

\n" "If 'Multiple libraries' is checked, the program generates libraries named
" "   boardname_libraryname
\n" "where libraryname is the name of the original library the parts are coming from. " "Otherwise a single project library with the name of the schematic or board is generated. " "In the latter case the assumption " "is made that equally named devices, symbols and packages are identical! No checks are " "performed if this is true. Violating this condition causes errors during the creation process.

\n" "Multiple Symbols

" "This parameter takes effect only if 'One library' is selected. If checked, the symbols of each individual " "library copied into the resulting library. This avoids errors due to " "symbols with the same name which are not identical.

" "Show scripts and file dialogs

" "If checked, you can edit the scripts and select path/filename for the library " "script and the log file before execution of the library generation script file.

\n" "Save log file

" "If checked, the logfile is saved before execution of the library generation script file.

\n" "Working path

" "Enter the path where the libraries and the log file go to, or use 'Browse' to select the directory.

\n" "Collect data, Create library

" "Use these buttons in this order to create the project library or libraries.
" "If one of the library files to be created already exists, you will be propted if " "the existing file may be deleted." ; void DisplayHelp(void) { dlgDialog("Bill Of Material - Help") { dlgHBoxLayout dlgSpacing(400); dlgHBoxLayout { dlgVBoxLayout dlgSpacing(300); dlgTextView(HelpText); } dlgHBoxLayout { dlgStretch(1); dlgPushButton("-Close") dlgReject(); } }; } string get_project_path() { if (board) board(B) return(filedir(B.name)); if (schematic) schematic(B) return(filedir(B.name)); if (library) library(B) return(filedir(B.name)); } 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 + "'"; } int exist_file(string FileName) { string a[]; int n = fileglob(a, FileName); if (n == 0) return 0; else return 1; } void OutputLayers(UL_LAYER L) { int l = L.number; if ((l==1) || ((l>15) && (l<=51)) || ((l>=91) && (l<=96)) ||(l>=100)) { h = ""; sprintf(h, "Layer %d %s;\n", L.number, L.name); cmd += h; } } void CreateHeader(UL_LIBRARY LBR) { LBR.layers(L) OutputLayers(L); h = ""; sprintf(h, "Set Wire_bend 2;\nSet Select_factor 0;\nSet Undo_log off;\n"); cmd += h; h = ""; sprintf(h, "Grid mic 1;\n"); cmd += h; h = ""; sprintf(h, "Display All;\n"); cmd += h; cmd += "DESCRIPTION "+replacenewline(LBR.description)+";\n"; } void CreateTrailer(void) { h = ""; sprintf(h, "Set Undo_log On;\nSet Select_factor 0.02;\nGrid last;\n"); cmd += h; } void PrintMovedLayer(int LNr, int Offset) { h = ""; sprintf(h, "Layer %d L$%d;\n", LNr + Offset, LNr + Offset); cmd += h; h = ""; sprintf(h, "Layer %d;\n", LNr + Offset); cmd += h; // logfile h = ""; sprintf(h, "%s.lbr: Moved Object from Layer %d to Layer %d\n", CurrentLbrName, LNr, LNr + Offset); logf += h; Status = h; dlgRedisplay(); } void PrintValidLayer(int LNr) { /* Move the following layers to always 52-90 to 150-190 always 97-99 to 191-193 package 91-96 to 194-199 symbol 1-51 to 200-248 */ int AlwOffset1 = 100; int AlwOffset2 = 94; int PackOffset = 103; int SymbOffset = 199; if ((LNr >= 52) && (LNr <= 90)) PrintMovedLayer(LNr, AlwOffset1); if ((LNr >= 97) && (LNr <= 99)) PrintMovedLayer(LNr, AlwOffset2); if (IsPackage) { if ((LNr >= 91) && (LNr <= 96)) /* forbidden layers */ PrintMovedLayer(LNr, PackOffset); else if ((LNr<=51) || (LNr >=100)) h = ""; sprintf(h, "Layer %d;\n", LNr); cmd += h; } else { /* symbol */ if (LNr <= 51) /* forbidden layers */ PrintMovedLayer(LNr, SymbOffset); else if (((LNr>=91) && (LNr <=96)) || (LNr>=100)) h = ""; sprintf(h, "Layer %d;\n", LNr); cmd += h; }; } void DrawArc(UL_ARC A) { PrintValidLayer(A.layer); h = ""; sprintf(h, "Arc CCW %f (%f %f) (%f %f) (%f %f);\n", u2mic(A.width), u2mic(A.x1), u2mic(A.y1), u2mic(A.xc + A.xc - A.x1), u2mic(A.yc + A.yc - A.y1), u2mic(A.x2), u2mic(A.y2)); cmd += h; } void DrawCircle(UL_CIRCLE C) { PrintValidLayer(C.layer); h = ""; sprintf(h, "Circle %f (%f %f) (%f %f);\n", u2mic(C.width), u2mic(C.x), u2mic(C.y), u2mic(C.x + C.radius), u2mic(C.y)); cmd += h; } void DrawWire(UL_WIRE W) { PrintValidLayer(W.layer); h = ""; sprintf(h, "Wire %f (%f %f) (%f %f);\n", u2mic(W.width), u2mic(W.x1), u2mic(W.y1), u2mic(W.x2), u2mic(W.y2)); cmd += h; } void DrawRectangle(UL_RECTANGLE R) { PrintValidLayer(R.layer); h = ""; sprintf(h, "Rect (%f %f) (%f %f);\n", u2mic(R.x1), u2mic(R.y1), u2mic(R.x2), u2mic(R.y2)); cmd += h; } void DrawContact(UL_CONTACT C) { string ShapeString; if (C.pad) { switch(C.pad.shape[1]) { case PAD_SHAPE_SQUARE : ShapeString = "Square"; break; case PAD_SHAPE_ROUND : ShapeString = "Round"; break; case PAD_SHAPE_OCTAGON : ShapeString = "Octagon"; break; case PAD_SHAPE_XLONGOCT : ShapeString = "Xlongoct";break; case PAD_SHAPE_YLONGOCT : ShapeString = "Ylongoct"; } h = ""; sprintf(h, "Change Drill %f;\n", u2mic(C.pad.drill)); cmd += h; h = ""; sprintf(h, "Pad %f %s '%s' (%f %f);\n", u2mic(C.pad.diameter[1]), ShapeString, C.pad.name, u2mic(C.pad.x), u2mic(C.pad.y)); cmd += h; } else if (C.smd) { PrintValidLayer(C.smd.layer); h = ""; sprintf(h, "CHANGE Roundness %d;\n", C.smd.roundness); cmd += h; h = ""; sprintf(h, "SMD %f %f '%s' (%f %f);\n", u2mic(C.smd.dx), u2mic(C.smd.dy), C.smd.name, u2mic(C.smd.x), u2mic(C.smd.y)); cmd += h; } } void DrawText(UL_TEXT T) { string s = "R0"; if (T.angle == 90) (s = "R90"); if (T.angle == 180) (s = "R180"); if (T.angle == 270) (s = "R270"); PrintValidLayer(T.layer); h = ""; sprintf(h, "Change Size %f;\n", u2mic(T.size)); cmd += h; h = ""; sprintf(h, "Change Ratio %d;\n", T.ratio); cmd += h; h = ""; sprintf(h, "Text '%s' %s (%f %f);\n", T.value, s, u2mic(T.x), u2mic(T.y)); cmd += h; if (T.mirror) {h = ""; sprintf(h, "Mirror (%f %f);\n", u2mic(T.x), u2mic(T.y)); cmd += h;}; } void DrawHole(UL_HOLE H) { h = ""; sprintf(h, "Change Drill %f;\n", u2mic(H.drill)); cmd += h; h = ""; sprintf(h, "Hole (%f %f);\n", u2mic(H.x), u2mic(H.y)); cmd += h; } void DrawPolygon(UL_POLYGON PL) { PrintValidLayer(PL.layer); h = ""; sprintf(h, "Change Isolate %f;\n", u2mic(PL.isolate)); cmd += h; h = ""; sprintf(h, "Change Spacing %f;\n", u2mic(PL.spacing)); cmd += h; if (PL.orphans) { h = ""; sprintf(h, "Change Orphans On;\n"); cmd += h; } else { h = ""; sprintf(h, "Change Orphans Off;\n"); cmd += h; } if (PL.thermals) { h = ""; sprintf(h, "Change Thermals On;\n"); cmd += h; } else { h = ""; sprintf(h, "Change Thermals Off;\n"); cmd += h; } if (PL.pour == POLYGON_POUR_SOLID) { h = ""; sprintf(h, "Change Pour Solid;\n"); cmd += h; } else { h = ""; sprintf(h, "Change Pour Hatch;\n"); cmd += h; } h = ""; sprintf(h, "Polygon %f ", u2mic(PL.width)); cmd += h; PL.wires(W) { h = ""; sprintf(h, "(%f %f) ", u2mic(W.x1), u2mic(W.y1)); cmd += h; /*start coord.*/ break; }; PL.wires(W) { h = ""; sprintf(h, "(%f %f) ", u2mic(W.x2), u2mic(W.y2)); cmd += h; }; h = ""; sprintf(h, ";\n"); cmd += h; } void DrawPin(UL_PIN P) { string DIR = "", FUNC = "", LEN = "", VIS = "", ANGLE = "R0"; if (P.angle == 90) (ANGLE = "R90"); if (P.angle == 180) (ANGLE = "R180"); if (P.angle == 270) (ANGLE = "R270"); if (P.function == PIN_FUNCTION_FLAG_NONE) (FUNC = "None"); if (P.function == PIN_FUNCTION_FLAG_DOT) (FUNC = "Dot"); if (P.function == PIN_FUNCTION_FLAG_CLK) (FUNC = "Clk"); if (P.function == (PIN_FUNCTION_FLAG_DOT | PIN_FUNCTION_FLAG_CLK)) (FUNC = "DotClk"); if (P.visible == PIN_VISIBLE_FLAG_OFF) (VIS = "Off"); if (P.visible == PIN_VISIBLE_FLAG_PIN) (VIS = "Pin"); if (P.visible == PIN_VISIBLE_FLAG_PAD) (VIS = "Pad"); if (P.visible == (PIN_VISIBLE_FLAG_PIN | PIN_VISIBLE_FLAG_PAD)) (VIS = "Both"); switch(P.direction) { case PIN_DIRECTION_NC : DIR = "NC"; break; case PIN_DIRECTION_IN : DIR = "In"; break; case PIN_DIRECTION_OUT : DIR = "Out"; break; case PIN_DIRECTION_IO : DIR = "I/O"; break; case PIN_DIRECTION_OC : DIR = "OC"; break; case PIN_DIRECTION_PWR : DIR = "Pwr"; break; case PIN_DIRECTION_PAS : DIR = "Pas"; break; case PIN_DIRECTION_HIZ : DIR = "Hiz"; break; case PIN_DIRECTION_SUP : DIR = "Sup"; } switch(P.length) { case PIN_LENGTH_POINT : LEN = "Point"; break; case PIN_LENGTH_SHORT : LEN = "Short"; break; case PIN_LENGTH_MIDDLE : LEN = "Middle"; break; case PIN_LENGTH_LONG : LEN = "Long"; } h = ""; sprintf(h, "Pin '%s' %s %s %s %s %s %d (%f %f);\n", P.name, DIR, FUNC, LEN, ANGLE, VIS, P.swaplevel, u2mic(P.x), u2mic(P.y)); cmd += h; } void DrawSymbol(UL_SYMBOL S) { IsPackage = 0; S.circles(C) DrawCircle(C); S.rectangles(R) DrawRectangle(R); S.wires(W) DrawWire(W); S.arcs(A) DrawArc(A); S.pins(P) DrawPin(P); S.texts(T) DrawText(T); S.polygons(PL) DrawPolygon(PL); } void DrawPackage(UL_PACKAGE P) { IsPackage = 1; P.arcs(A) DrawArc(A); P.circles(C) DrawCircle(C); P.wires(W) DrawWire(W); P.rectangles(R) DrawRectangle(R); P.contacts(C) DrawContact(C); P.texts(T) DrawText(T); P.holes(H) DrawHole(H); P.polygons(PL) DrawPolygon(PL); } void DrawDevice(UL_DEVICESET D, UL_LIBRARY LBR) { string GateAddlevel; string symname; cmd += "DESCRIPTION "+replacenewline(D.description)+";\n"; cmd += "PREFIX '"+D.prefix+"';\n"; cmd += "VALUE "+D.value+";\n"; D.gates(G) { switch (G.addlevel) { case GATE_ADDLEVEL_NEXT : GateAddlevel = "Next"; break; case GATE_ADDLEVEL_MUST : GateAddlevel = "Must"; break; case GATE_ADDLEVEL_CAN : GateAddlevel = "Can"; break; case GATE_ADDLEVEL_REQUEST : GateAddlevel = "Request"; break; case GATE_ADDLEVEL_ALWAYS : GateAddlevel = "Always"; }; h = ""; sprintf(h, "CHANGE Addlevel %s;\n", GateAddlevel); cmd += h; h = ""; sprintf(h, "CHANGE Swaplevel %d;\n", G.swaplevel); cmd += h; if (multiple_symbols) symname = LBR.name+"_"+G.symbol.name; else symname = G.symbol.name; h = ""; sprintf(h, "ADD %s '%s' (%f %f);\n", symname ,G.name, u2mic(G.x), u2mic(G.y)); cmd += h; } D.devices(DV) { if (DV.package) { cmd += "PACKAGE '"+DV.package.name+"' "+DV.name+";\n"; cmd += "TECHNOLOGY "+DV.technologies+";\n"; } DV.gates(G) { G.symbol.pins(P) { if (DV.package) { h = ""; sprintf(h, "CONNECT %s.%s %s;\n", G.name, P.name, P.contact.name); cmd += h; } } } } } // void OutputUnmistakablePackages (UL_LIBRARY LBR) { PrevName = ""; if (exist_file(WorkPath+CurrentLbrName+".lbr")) { h = ""; sprintf(h, "REMOVE %s;\n", WorkPath+CurrentLbrName+".lbr"); cmd += h; // delete exitsting lbr } h = ""; sprintf(h, "OPEN %s.lbr;\n", WorkPath+CurrentLbrName); cmd += h; CreateHeader(LBR); LBR.packages(P) { if (PrevName != P.name) { logf += " PAC: "+P.name+"\n"; Status = " PAC: "+P.name; dlgRedisplay(); NameIndex = 0; h = ""; sprintf(h, "Edit %s.PAC;\n", P.name); cmd += h; DrawPackage(P); } else { NameIndex++; h = ""; sprintf(h, "Edit %s$%02d.PAC;\n", P.name, NameIndex); cmd += h; //logfile h = ""; sprintf(h, " PAC: %s renamed to %s$%02d\n", P.name, P.name, NameIndex); logf += h; Status = h; dlgRedisplay(); // end logfile DrawPackage(P); } PrevName = P.name; cmd += "DESCRIPTION "+replacenewline(P.description)+";\n"; } } void OutputUnmistakableSymbols (UL_LIBRARY LBR) { PrevName = ""; LBR.symbols(S) { if (PrevName != S.name) { logf += " SYM: "+S.name+"\n"; Status = " SYM: "+S.name; dlgRedisplay(); NameIndex = 0; h = ""; sprintf(h, "Edit %s.SYM;\n", S.name); cmd += h; DrawSymbol(S); } else { NameIndex = NameIndex + 1; h = ""; sprintf(h, "Edit %s$%02d.SYM;\n", S.name, NameIndex); cmd += h; // logfile h = ""; sprintf(h, " SYM: %s renamed to %s$%02d\n", S.name, S.name, NameIndex); logf += h; Status = h; dlgRedisplay(); // end logfile DrawSymbol(S); } PrevName = S.name; } } void OutputUnmistakableDevices (UL_LIBRARY LBR) { PrevName = ""; LBR.devicesets(D) { if (PrevName != D.name) { logf += " DEV: "+D.name+"\n"; Status = " DEV: "+D.name; dlgRedisplay(); NameIndex = 0; h = ""; sprintf(h, "Edit %s.DEV;\n", D.name); cmd += h; DrawDevice(D, LBR); } else { NameIndex = NameIndex + 1; h = ""; sprintf(h, "Edit %s$%02d.DEV;\n", D.name, NameIndex); cmd += h; // logfile h = ""; sprintf(h, " DEV: %s renamed to %s$%02d\n", D.name, D.name, NameIndex); logf += h; Status = h; dlgRedisplay(); DrawDevice(D, LBR); } PrevName = D.name; } } // ----------- void make_lbr(void) { if (board) board(B) { B.libraries(LBR) { CurrentLbrName = filesetext(EditName, "")+"_"+LBR.name; LBR.packages(PAC) { logf += "LIBRARY: "+CurrentLbrName+".lbr\n"; OutputUnmistakablePackages(LBR); cmd += "WRITE;\n"; break; } } CreateTrailer(); } if (schematic) schematic(SCH) { SCH.libraries(LBR) { CurrentLbrName = filesetext(EditName, "")+"_"+LBR.name; LBR.devices(DEV) { logf += "LIBRARY: "+CurrentLbrName+".lbr\n"; OutputUnmistakablePackages(LBR); OutputUnmistakableSymbols(LBR); OutputUnmistakableDevices(LBR); cmd += "WRITE;\n"; break; }; } CreateTrailer(); } } // ---------------------------------------------------------------------------------------- int is_new(void) { // n = nr of entries int i; if (n == 0) return 1; for (i = 0; i < n; i++) { if (x[n] == x[i]) { return(0); } } return 1; } void CreateOneLibHeader(UL_LIBRARY LBR) { if (exist_file(WorkPath+CurrentLbrName+".lbr")) { h = ""; sprintf(h, "REMOVE %s;\n", WorkPath+CurrentLbrName+".lbr"); cmd += h; // delete exitsting lbr } h = ""; sprintf(h, "OPEN %s.lbr;\n", WorkPath+CurrentLbrName); cmd += h; CreateHeader(LBR); } // --------- void OutputPackages (UL_LIBRARY LBR) { LBR.packages(P) { n++; x[n] = P.name; if (is_new()) { logf += " PAC: "+P.name+"\n"; Status = " PAC: "+P.name; dlgRedisplay(); h = ""; sprintf(h, "Edit %s.PAC;\n", P.name); cmd += h; DrawPackage(P); cmd += "DESCRIPTION "+replacenewline(P.description)+";\n"; } else { logf += " not used PAC: "+P.name+"\n"; Status = " PAC: "+P.name; dlgRedisplay(); } } } void OutputSymbols (UL_LIBRARY LBR) { string symname; LBR.symbols(S) { if (multiple_symbols) symname = LBR.name+"_"+S.name; else symname = S.name; n++; x[n] = symname; if (is_new()) { logf += " SYM: "+symname+"\n"; Status = " SYM: "+S.name; dlgRedisplay(); h = ""; sprintf(h, "Edit %s.SYM;\n", symname); cmd += h; DrawSymbol(S); } else { logf += " not used SYM: "+symname+"\n"; Status = " SYM: "+S.name; dlgRedisplay(); } } } void OutputDevices (UL_LIBRARY LBR) { LBR.devicesets(D) { n++; x[n] = D.name; if (is_new()) { logf += " DEV: "+D.name+"\n"; Status = " DEV: "+D.name; dlgRedisplay(); NameIndex = 0; h = ""; sprintf(h, "Edit %s.DEV;\n", D.name); cmd += h; DrawDevice(D, LBR); } else { logf += " not used DEV: "+D.name+"\n"; Status = " DEV: "+D.name; dlgRedisplay(); } } } // ------------ void make_one_lbr(void) { if (board) board(B) { B.libraries(LBR) { CurrentLbrName = filesetext(EditName, ""); logf += "LIBRARY: "+CurrentLbrName+".lbr\n"; CreateOneLibHeader(LBR); break; } n = 0; B.libraries(LBR) { LBR.packages(PAC) { OutputPackages(LBR); } } cmd += "WRITE;\n"; CreateTrailer(); } if (schematic) schematic(SCH) { SCH.libraries(LBR) { CurrentLbrName = filesetext(EditName, ""); logf += "LIBRARY: "+CurrentLbrName+".lbr\n"; CreateOneLibHeader(LBR); break; } n = 0; SCH.libraries(LBR) { LBR.devices(DEV) { OutputPackages(LBR); } } n = 0; SCH.libraries(LBR) { LBR.devices(DEV) { OutputSymbols(LBR); } } n = 0; SCH.libraries(LBR) { LBR.devices(DEV) { OutputDevices(LBR); } } cmd += "WRITE;\n"; CreateTrailer(); } } // ----------- void show_save_log_file(string cm) { if(show_script) { int R = dlgDialog("Save Log File") { dlgVBoxLayout { dlgLabel("Edit only if you are sure what you do!"); dlgTextEdit(cm); dlgHBoxLayout { dlgPushButton("+Ok") dlgAccept(); dlgPushButton("-Cancel") dlgReject(); } } }; if (R) { LogName = dlgFileSave("Save Script File", WorkPath+PureLogName, "*.log"); if (LogName != "") output(LogName, "wt") printf(cm); } } else { output(WorkPath+PureLogName, "wt") printf(cm); } } // ----------- void show_save_script_file(string cm) { if (show_script) { int R = dlgDialog("Save Script File") { dlgVBoxLayout { dlgLabel("Edit only if you are sure what you do!"); dlgTextEdit(cm); dlgHBoxLayout { dlgPushButton("+Ok") dlgAccept(); dlgPushButton("-Cancel") dlgReject(); } } }; if (R) { ScriptName = dlgFileSave("Save Script File", WorkPath+PureScriptName, "*.scr"); if (ScriptName != "") output(ScriptName, "wt") printf(cm); } } else { ScriptName = WorkPath+PureScriptName; output(ScriptName, "wt") printf(cm); } } //------------ main ---------------------------------------- if (library) { dlgMessageBox(usage + "ERROR


This program can only work in the schematic or package editor."); exit(1); } else { if (board) board(B) EditName = filename(B.name); // name of loaded board/schematic w/o path if (schematic) schematic(S) EditName = filename(S.name); } PureScriptName = filesetext(EditName, ".scr"); // name of generated script w/o path PureLogName = filesetext(EditName, ".log"); // name of generated log msgs w/o path WorkPath = get_project_path(); int Result = dlgDialog("Create Project Library") { string globList[]; int globListIndex = -1; int globCnt = 0; dlgHBoxLayout { dlgStretch(1); dlgSpacing(500); dlgStretch(1); } dlgHBoxLayout { dlgVBoxLayout { dlgGroup("Creation Mode") { dlgRadioButton("&Multiple libraries", onelib); dlgRadioButton("&One library", onelib); dlgCheckBox("Multiple symbols", multiple_symbols); } dlgGroup("User Interface") { dlgCheckBox("Show scripts and file dialogs", show_script); dlgCheckBox("Save log file", save_log); } } dlgVBoxLayout { dlgLabel("Log file"); dlgTextView(logf); } } dlgHBoxLayout { dlgLabel(" &Working path:"); dlgStringEdit(WorkPath); dlgPushButton("Bro&wse") { string NewFileName; h = WorkPath; WorkPath = dlgDirectory("Select a directory", WorkPath); if (WorkPath == "") WorkPath = h; } } dlgSpacing(10); dlgHBoxLayout { dlgLabel(Status, 1); dlgStretch(1); dlgPushButton("+&Collect data") {logf = "Project Library Creation Log File "+t2string(time())+"\n" +EAGLE_SIGNATURE+"\nCreated from: "+EditName+"\n\n"; if (onelib) make_one_lbr(); else make_lbr(); show_save_script_file(cmd); Status = ""; dlgRedisplay(); if (save_log) show_save_log_file(logf); } dlgPushButton("Create &library") {if (cmd == "") dlgMessageBox("Use 'Collect data' first!","&OK"); else exit("SCRIPT "+ScriptName+";\n"); } dlgPushButton("-&Quit") dlgReject(); dlgSpacing(23); dlgPushButton("&Help") DisplayHelp(); } };