pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 #ifdef HAVE_CONFIG_H 00002 #include "config.h" 00003 #endif 00004 00005 #include <stdio.h> 00006 #include <stdarg.h> 00007 #include <stdlib.h> 00008 #include <string.h> 00009 00010 #include "xincludes.h" 00011 00012 #include "compat.h" 00013 #include "global.h" 00014 #include "data.h" 00015 #include "crosshair.h" 00016 #include "misc.h" 00017 #include "pcb-printf.h" 00018 00019 #include "hid.h" 00020 #include "../hidint.h" 00021 #include "lesstif.h" 00022 00023 #ifdef HAVE_LIBDMALLOC 00024 #include <dmalloc.h> 00025 #endif 00026 00027 #define CRASH fprintf(stderr, "HID error: pcb called unimplemented GUI function %s\n", __FUNCTION__), abort() 00028 00029 static Arg args[30]; 00030 static int n; 00031 #define stdarg(t,v) XtSetArg(args[n], t, v); n++ 00032 00033 static int ok; 00034 00035 #define TOP_SIDE_NAME "(top)" 00036 #define BOTTOM_SIDE_NAME "(bottom)" 00037 00038 /* ------------------------------------------------------------ */ 00039 00040 static void 00041 dialog_callback (Widget w, void *v, void *cbs) 00042 { 00043 ok = (int) (size_t) v; 00044 } 00045 00046 static int 00047 wait_for_dialog (Widget w) 00048 { 00049 ok = -1; 00050 XtManageChild (w); 00051 while (ok == -1 && XtIsManaged (w)) 00052 { 00053 XEvent e; 00054 XtAppNextEvent (app_context, &e); 00055 XtDispatchEvent (&e); 00056 } 00057 XtUnmanageChild (w); 00058 return ok; 00059 } 00060 00061 /* ------------------------------------------------------------ */ 00062 00063 static Widget fsb = 0; 00064 static XmString xms_pcb, xms_net, xms_vend, xms_all, xms_load, xms_loadv, 00065 xms_save, xms_fp; 00066 00067 static void 00068 setup_fsb_dialog () 00069 { 00070 if (fsb) 00071 return; 00072 00073 xms_pcb = XmStringCreatePCB ("*.pcb"); 00074 xms_fp = XmStringCreatePCB ("*.fp"); 00075 xms_net = XmStringCreatePCB ("*.net"); 00076 xms_vend = XmStringCreatePCB ("*.vend"); 00077 xms_all = XmStringCreatePCB ("*"); 00078 xms_load = XmStringCreatePCB ("Load From"); 00079 xms_loadv = XmStringCreatePCB ("Load Vendor"); 00080 xms_save = XmStringCreatePCB ("Save As"); 00081 00082 n = 0; 00083 fsb = XmCreateFileSelectionDialog (mainwind, "file", args, n); 00084 00085 XtAddCallback (fsb, XmNokCallback, (XtCallbackProc) dialog_callback, 00086 (XtPointer) 1); 00087 XtAddCallback (fsb, XmNcancelCallback, (XtCallbackProc) dialog_callback, 00088 (XtPointer) 0); 00089 } 00090 00091 static const char load_syntax[] = 00092 "Load()\n" 00093 "Load(Layout|LayoutToBuffer|ElementToBuffer|Netlist|Revert)"; 00094 00095 static const char load_help[] = 00096 "Load layout data from a user-selected file."; 00097 00098 /* %start-doc actions Load 00099 00100 This action is a GUI front-end to the core's @code{LoadFrom} action 00101 (@pxref{LoadFrom Action}). If you happen to pass a filename, like 00102 @code{LoadFrom}, then @code{LoadFrom} is called directly. Else, the 00103 user is prompted for a filename to load, and then @code{LoadFrom} is 00104 called with that filename. 00105 00106 %end-doc */ 00107 00108 static int 00109 Load (int argc, char **argv, Coord x, Coord y) 00110 { 00111 const char *function; 00112 char *name; 00113 XmString xmname, pattern; 00114 00115 if (argc > 1) 00116 return hid_actionv ("LoadFrom", argc, argv); 00117 00118 function = argc ? argv[0] : "Layout"; 00119 00120 setup_fsb_dialog (); 00121 00122 if (strcasecmp (function, "Netlist") == 0) 00123 pattern = xms_net; 00124 else if (strcasecmp (function, "ElementToBuffer") == 0) 00125 pattern = xms_fp; 00126 else 00127 pattern = xms_pcb; 00128 00129 n = 0; 00130 stdarg (XmNtitle, "Load From"); 00131 XtSetValues (XtParent (fsb), args, n); 00132 00133 n = 0; 00134 stdarg (XmNpattern, pattern); 00135 stdarg (XmNmustMatch, True); 00136 stdarg (XmNselectionLabelString, xms_load); 00137 XtSetValues (fsb, args, n); 00138 00139 if (!wait_for_dialog (fsb)) 00140 return 1; 00141 00142 n = 0; 00143 stdarg (XmNdirSpec, &xmname); 00144 XtGetValues (fsb, args, n); 00145 00146 XmStringGetLtoR (xmname, XmFONTLIST_DEFAULT_TAG, &name); 00147 00148 hid_actionl ("LoadFrom", function, name, NULL); 00149 00150 XtFree (name); 00151 00152 return 0; 00153 } 00154 00155 static const char loadvendor_syntax[] = 00156 "LoadVendor()"; 00157 00158 static const char loadvendor_help[] = 00159 "Loads a user-selected vendor resource file."; 00160 00161 /* %start-doc actions LoadVendor 00162 00163 The user is prompted for a file to load, and then 00164 @code{LoadVendorFrom} is called (@pxref{LoadVendorFrom Action}) to 00165 load that vendor file. 00166 00167 %end-doc */ 00168 00169 static int 00170 LoadVendor (int argc, char **argv, Coord x, Coord y) 00171 { 00172 char *name; 00173 XmString xmname, pattern; 00174 00175 if (argc > 0) 00176 return hid_actionv ("LoadVendorFrom", argc, argv); 00177 00178 setup_fsb_dialog (); 00179 00180 pattern = xms_vend; 00181 00182 n = 0; 00183 stdarg (XmNtitle, "Load Vendor"); 00184 XtSetValues (XtParent (fsb), args, n); 00185 00186 n = 0; 00187 stdarg (XmNpattern, pattern); 00188 stdarg (XmNmustMatch, True); 00189 stdarg (XmNselectionLabelString, xms_loadv); 00190 XtSetValues (fsb, args, n); 00191 00192 if (!wait_for_dialog (fsb)) 00193 return 1; 00194 00195 n = 0; 00196 stdarg (XmNdirSpec, &xmname); 00197 XtGetValues (fsb, args, n); 00198 00199 XmStringGetLtoR (xmname, XmFONTLIST_DEFAULT_TAG, &name); 00200 00201 hid_actionl ("LoadVendorFrom", name, NULL); 00202 00203 XtFree (name); 00204 00205 return 0; 00206 } 00207 00208 static const char save_syntax[] = 00209 "Save()\n" 00210 "Save(Layout|LayoutAs)\n" 00211 "Save(AllConnections|AllUnusedPins|ElementConnections)\n" 00212 "Save(PasteBuffer)"; 00213 00214 static const char save_help[] = 00215 "Save layout data to a user-selected file."; 00216 00217 /* %start-doc actions Save 00218 00219 This action is a GUI front-end to the core's @code{SaveTo} action 00220 (@pxref{SaveTo Action}). If you happen to pass a filename, like 00221 @code{SaveTo}, then @code{SaveTo} is called directly. Else, the 00222 user is prompted for a filename to save, and then @code{SaveTo} is 00223 called with that filename. 00224 00225 %end-doc */ 00226 00227 static int 00228 Save (int argc, char **argv, Coord x, Coord y) 00229 { 00230 const char *function; 00231 char *name; 00232 XmString xmname, pattern; 00233 00234 if (argc > 1) 00235 hid_actionv ("SaveTo", argc, argv); 00236 00237 function = argc ? argv[0] : "Layout"; 00238 00239 if (strcasecmp (function, "Layout") == 0) 00240 if (PCB->Filename) 00241 return hid_actionl ("SaveTo", "Layout", PCB->Filename, NULL); 00242 00243 setup_fsb_dialog (); 00244 00245 pattern = xms_pcb; 00246 00247 XtManageChild (fsb); 00248 00249 n = 0; 00250 stdarg (XmNtitle, "Save As"); 00251 XtSetValues (XtParent (fsb), args, n); 00252 00253 n = 0; 00254 stdarg (XmNpattern, pattern); 00255 stdarg (XmNmustMatch, False); 00256 stdarg (XmNselectionLabelString, xms_save); 00257 XtSetValues (fsb, args, n); 00258 00259 if (!wait_for_dialog (fsb)) 00260 return 1; 00261 00262 n = 0; 00263 stdarg (XmNdirSpec, &xmname); 00264 XtGetValues (fsb, args, n); 00265 00266 XmStringGetLtoR (xmname, XmFONTLIST_DEFAULT_TAG, &name); 00267 00268 if (strcasecmp (function, "PasteBuffer") == 0) 00269 hid_actionl ("PasteBuffer", "Save", name, NULL); 00270 else 00271 { 00272 /* 00273 * if we got this far and the function is Layout, then 00274 * we really needed it to be a LayoutAs. Otherwise 00275 * ActionSaveTo() will ignore the new file name we 00276 * just obtained. 00277 */ 00278 if (strcasecmp (function, "Layout") == 0) 00279 hid_actionl ("SaveTo", "LayoutAs", name, NULL); 00280 else 00281 hid_actionl ("SaveTo", function, name, NULL); 00282 } 00283 XtFree (name); 00284 00285 return 0; 00286 } 00287 00288 /* ------------------------------------------------------------ */ 00289 00290 static Widget log_form, log_text; 00291 static int log_size = 0; 00292 static int pending_newline = 0; 00293 00294 static void 00295 log_clear (Widget w, void *up, void *cbp) 00296 { 00297 XmTextSetString (log_text, ""); 00298 log_size = 0; 00299 pending_newline = 0; 00300 } 00301 00302 static void 00303 log_dismiss (Widget w, void *up, void *cbp) 00304 { 00305 XtUnmanageChild (log_form); 00306 } 00307 00308 void 00309 lesstif_logv (const char *fmt, va_list ap) 00310 { 00311 gchar *buf, *scan; 00312 if (!mainwind) 00313 { 00314 vprintf (fmt, ap); 00315 return; 00316 } 00317 if (!log_form) 00318 { 00319 Widget clear_button, dismiss_button; 00320 00321 n = 0; 00322 stdarg (XmNautoUnmanage, False); 00323 stdarg (XmNwidth, 600); 00324 stdarg (XmNheight, 200); 00325 stdarg (XmNtitle, "PCB Log"); 00326 log_form = XmCreateFormDialog (mainwind, "log", args, n); 00327 00328 n = 0; 00329 stdarg (XmNrightAttachment, XmATTACH_FORM); 00330 stdarg (XmNbottomAttachment, XmATTACH_FORM); 00331 clear_button = XmCreatePushButton (log_form, "clear", args, n); 00332 XtManageChild (clear_button); 00333 XtAddCallback (clear_button, XmNactivateCallback, 00334 (XtCallbackProc) log_clear, 0); 00335 00336 n = 0; 00337 stdarg (XmNrightAttachment, XmATTACH_WIDGET); 00338 stdarg (XmNrightWidget, clear_button); 00339 stdarg (XmNbottomAttachment, XmATTACH_FORM); 00340 dismiss_button = XmCreatePushButton (log_form, "dismiss", args, n); 00341 XtManageChild (dismiss_button); 00342 XtAddCallback (dismiss_button, XmNactivateCallback, 00343 (XtCallbackProc) log_dismiss, 0); 00344 00345 n = 0; 00346 stdarg (XmNeditable, False); 00347 stdarg (XmNeditMode, XmMULTI_LINE_EDIT); 00348 stdarg (XmNcursorPositionVisible, True); 00349 stdarg (XmNtopAttachment, XmATTACH_FORM); 00350 stdarg (XmNleftAttachment, XmATTACH_FORM); 00351 stdarg (XmNrightAttachment, XmATTACH_FORM); 00352 stdarg (XmNbottomAttachment, XmATTACH_WIDGET); 00353 stdarg (XmNbottomWidget, clear_button); 00354 log_text = XmCreateScrolledText (log_form, "text", args, n); 00355 XtManageChild (log_text); 00356 00357 XtManageChild (log_form); 00358 } 00359 if (pending_newline) 00360 { 00361 XmTextInsert (log_text, log_size++, "\n"); 00362 pending_newline = 0; 00363 } 00364 buf = pcb_vprintf (fmt, ap); 00365 scan = &buf[strlen (buf) - 1]; 00366 while (scan >= buf && *scan == '\n') 00367 { 00368 pending_newline++; 00369 *scan-- = 0; 00370 } 00371 XmTextInsert (log_text, log_size, buf); 00372 log_size += strlen (buf); 00373 00374 scan = strrchr(buf, '\n'); 00375 if (scan) 00376 scan++; 00377 else 00378 scan = buf; 00379 XmTextSetCursorPosition (log_text, log_size - strlen(scan)); 00380 g_free (buf); 00381 } 00382 00383 void 00384 lesstif_log (const char *fmt, ...) 00385 { 00386 va_list ap; 00387 va_start (ap, fmt); 00388 lesstif_logv (fmt, ap); 00389 va_end (ap); 00390 } 00391 00392 /* ------------------------------------------------------------ */ 00393 00394 static Widget confirm_dialog = 0; 00395 static Widget confirm_cancel, confirm_ok, confirm_label; 00396 00397 int 00398 lesstif_confirm_dialog (char *msg, ...) 00399 { 00400 char *cancelmsg, *okmsg; 00401 va_list ap; 00402 XmString xs; 00403 00404 if (mainwind == 0) 00405 return 1; 00406 00407 if (confirm_dialog == 0) 00408 { 00409 n = 0; 00410 stdarg (XmNdefaultButtonType, XmDIALOG_OK_BUTTON); 00411 stdarg (XmNtitle, "Confirm"); 00412 confirm_dialog = XmCreateQuestionDialog (mainwind, "confirm", args, n); 00413 XtAddCallback (confirm_dialog, XmNcancelCallback, 00414 (XtCallbackProc) dialog_callback, (XtPointer) 0); 00415 XtAddCallback (confirm_dialog, XmNokCallback, 00416 (XtCallbackProc) dialog_callback, (XtPointer) 1); 00417 00418 confirm_cancel = 00419 XmMessageBoxGetChild (confirm_dialog, XmDIALOG_CANCEL_BUTTON); 00420 confirm_ok = XmMessageBoxGetChild (confirm_dialog, XmDIALOG_OK_BUTTON); 00421 confirm_label = 00422 XmMessageBoxGetChild (confirm_dialog, XmDIALOG_MESSAGE_LABEL); 00423 XtUnmanageChild (XmMessageBoxGetChild 00424 (confirm_dialog, XmDIALOG_HELP_BUTTON)); 00425 } 00426 00427 va_start (ap, msg); 00428 cancelmsg = va_arg (ap, char *); 00429 okmsg = va_arg (ap, char *); 00430 va_end (ap); 00431 00432 if (!cancelmsg) 00433 { 00434 cancelmsg = "Cancel"; 00435 okmsg = "Ok"; 00436 } 00437 00438 n = 0; 00439 xs = XmStringCreatePCB (cancelmsg); 00440 00441 if (okmsg) 00442 { 00443 stdarg (XmNcancelLabelString, xs); 00444 xs = XmStringCreatePCB (okmsg); 00445 XtManageChild (confirm_cancel); 00446 } 00447 else 00448 XtUnmanageChild (confirm_cancel); 00449 00450 stdarg (XmNokLabelString, xs); 00451 00452 xs = XmStringCreatePCB (msg); 00453 stdarg (XmNmessageString, xs); 00454 XtSetValues (confirm_dialog, args, n); 00455 00456 wait_for_dialog (confirm_dialog); 00457 00458 n = 0; 00459 stdarg (XmNdefaultPosition, False); 00460 XtSetValues (confirm_dialog, args, n); 00461 00462 return ok; 00463 } 00464 00465 static int 00466 ConfirmAction (int argc, char **argv, Coord x, Coord y) 00467 { 00468 int rv = lesstif_confirm_dialog (argc > 0 ? argv[0] : 0, 00469 argc > 1 ? argv[1] : 0, 00470 argc > 2 ? argv[2] : 0, 00471 0); 00472 return rv; 00473 } 00474 00475 /* ------------------------------------------------------------ */ 00476 00477 int 00478 lesstif_close_confirm_dialog () 00479 { 00480 return lesstif_confirm_dialog ("OK to lose data ?", NULL); 00481 } 00482 00483 /* ------------------------------------------------------------ */ 00484 00485 static Widget report = 0, report_form; 00486 00487 void 00488 lesstif_report_dialog (char *title, char *msg) 00489 { 00490 if (!report) 00491 { 00492 if (mainwind == 0) 00493 return; 00494 00495 n = 0; 00496 stdarg (XmNautoUnmanage, False); 00497 stdarg (XmNwidth, 600); 00498 stdarg (XmNheight, 200); 00499 stdarg (XmNtitle, title); 00500 report_form = XmCreateFormDialog (mainwind, "report", args, n); 00501 00502 n = 0; 00503 stdarg (XmNeditable, False); 00504 stdarg (XmNeditMode, XmMULTI_LINE_EDIT); 00505 stdarg (XmNcursorPositionVisible, False); 00506 stdarg (XmNtopAttachment, XmATTACH_FORM); 00507 stdarg (XmNleftAttachment, XmATTACH_FORM); 00508 stdarg (XmNrightAttachment, XmATTACH_FORM); 00509 stdarg (XmNbottomAttachment, XmATTACH_FORM); 00510 report = XmCreateScrolledText (report_form, "text", args, n); 00511 XtManageChild (report); 00512 } 00513 n = 0; 00514 stdarg (XmNtitle, title); 00515 XtSetValues (report_form, args, n); 00516 XmTextSetString (report, msg); 00517 00518 XtManageChild (report_form); 00519 } 00520 00521 /* ------------------------------------------------------------ */ 00522 /* FIXME -- make this a proper file select dialog box */ 00523 char * 00524 lesstif_fileselect (const char *title, const char *descr, 00525 char *default_file, char *default_ext, 00526 const char *history_tag, int flags) 00527 { 00528 00529 return lesstif_prompt_for (title, default_file); 00530 } 00531 00532 /* ------------------------------------------------------------ */ 00533 00534 static Widget prompt_dialog = 0; 00535 static Widget prompt_label, prompt_text; 00536 00537 char * 00538 lesstif_prompt_for (const char *msg, const char *default_string) 00539 { 00540 char *rv; 00541 XmString xs; 00542 if (prompt_dialog == 0) 00543 { 00544 n = 0; 00545 stdarg (XmNautoUnmanage, False); 00546 stdarg (XmNtitle, "PCB Prompt"); 00547 prompt_dialog = XmCreateFormDialog (mainwind, "prompt", args, n); 00548 00549 n = 0; 00550 stdarg (XmNtopAttachment, XmATTACH_FORM); 00551 stdarg (XmNleftAttachment, XmATTACH_FORM); 00552 stdarg (XmNrightAttachment, XmATTACH_FORM); 00553 stdarg (XmNalignment, XmALIGNMENT_BEGINNING); 00554 prompt_label = XmCreateLabel (prompt_dialog, "label", args, n); 00555 XtManageChild (prompt_label); 00556 00557 n = 0; 00558 stdarg (XmNtopAttachment, XmATTACH_WIDGET); 00559 stdarg (XmNtopWidget, prompt_label); 00560 stdarg (XmNbottomAttachment, XmATTACH_WIDGET); 00561 stdarg (XmNleftAttachment, XmATTACH_FORM); 00562 stdarg (XmNrightAttachment, XmATTACH_FORM); 00563 stdarg (XmNeditable, True); 00564 prompt_text = XmCreateText (prompt_dialog, "text", args, n); 00565 XtManageChild (prompt_text); 00566 XtAddCallback (prompt_text, XmNactivateCallback, 00567 (XtCallbackProc) dialog_callback, (XtPointer) 1); 00568 } 00569 if (!default_string) 00570 default_string = ""; 00571 if (!msg) 00572 msg = "Enter text:"; 00573 n = 0; 00574 xs = XmStringCreatePCB ((char *)msg); 00575 stdarg (XmNlabelString, xs); 00576 XtSetValues (prompt_label, args, n); 00577 XmTextSetString (prompt_text, (char *)default_string); 00578 XmTextSetCursorPosition (prompt_text, strlen (default_string)); 00579 wait_for_dialog (prompt_dialog); 00580 rv = XmTextGetString (prompt_text); 00581 return rv; 00582 } 00583 00584 static const char promptfor_syntax[] = 00585 "PromptFor([message[,default]])"; 00586 00587 static const char promptfor_help[] = 00588 "Prompt for a response."; 00589 00590 /* %start-doc actions PromptFor 00591 00592 This is mostly for testing the lesstif HID interface. The parameters 00593 are passed to the @code{prompt_for()} HID function, causing the user 00594 to be prompted for a response. The respose is simply printed to the 00595 user's stdout. 00596 00597 %end-doc */ 00598 00599 static int 00600 PromptFor (int argc, char **argv, Coord x, Coord y) 00601 { 00602 char *rv = lesstif_prompt_for (argc > 0 ? argv[0] : 0, 00603 argc > 1 ? argv[1] : 0); 00604 printf ("rv = `%s'\n", rv); 00605 return 0; 00606 } 00607 00608 /* ------------------------------------------------------------ */ 00609 00610 static Widget 00611 create_form_ok_dialog (char *name, int ok) 00612 { 00613 Widget dialog, topform; 00614 n = 0; 00615 dialog = XmCreateQuestionDialog (mainwind, name, args, n); 00616 00617 XtUnmanageChild (XmMessageBoxGetChild (dialog, XmDIALOG_SYMBOL_LABEL)); 00618 XtUnmanageChild (XmMessageBoxGetChild (dialog, XmDIALOG_MESSAGE_LABEL)); 00619 XtUnmanageChild (XmMessageBoxGetChild (dialog, XmDIALOG_HELP_BUTTON)); 00620 XtAddCallback (dialog, XmNcancelCallback, (XtCallbackProc) dialog_callback, 00621 (XtPointer) 0); 00622 if (ok) 00623 XtAddCallback (dialog, XmNokCallback, (XtCallbackProc) dialog_callback, 00624 (XtPointer) 1); 00625 else 00626 XtUnmanageChild (XmMessageBoxGetChild (dialog, XmDIALOG_OK_BUTTON)); 00627 00628 n = 0; 00629 topform = XmCreateForm (dialog, "attributes", args, n); 00630 XtManageChild (topform); 00631 return topform; 00632 } 00633 00634 int 00635 lesstif_attribute_dialog (HID_Attribute * attrs, 00636 int n_attrs, HID_Attr_Val * results, 00637 const char * title, const char * descr) 00638 { 00639 Widget dialog, topform, lform, form; 00640 Widget *wl; 00641 int i, rv; 00642 static XmString empty = 0; 00643 int actual_nattrs = 0; 00644 int attrcount = 0; 00645 00646 if (!empty) 00647 empty = XmStringCreatePCB (" "); 00648 00649 for (i = 0; i < n_attrs; i++) 00650 { 00651 if (attrs[i].help_text != ATTR_UNDOCUMENTED) 00652 actual_nattrs ++; 00653 results[i] = attrs[i].default_val; 00654 if (results[i].str_value) 00655 results[i].str_value = strdup (results[i].str_value); 00656 } 00657 00658 wl = (Widget *) malloc (n_attrs * sizeof (Widget)); 00659 00660 topform = create_form_ok_dialog ((char *)title, 1); 00661 dialog = XtParent (topform); 00662 00663 n = 0; 00664 stdarg (XmNfractionBase, n_attrs); 00665 XtSetValues (topform, args, n); 00666 00667 n = 0; 00668 stdarg (XmNtopAttachment, XmATTACH_FORM); 00669 stdarg (XmNbottomAttachment, XmATTACH_FORM); 00670 stdarg (XmNleftAttachment, XmATTACH_FORM); 00671 stdarg (XmNfractionBase, actual_nattrs); 00672 lform = XmCreateForm (topform, "attributes", args, n); 00673 XtManageChild (lform); 00674 00675 n = 0; 00676 stdarg (XmNtopAttachment, XmATTACH_FORM); 00677 stdarg (XmNbottomAttachment, XmATTACH_FORM); 00678 stdarg (XmNleftAttachment, XmATTACH_WIDGET); 00679 stdarg (XmNleftWidget, lform); 00680 stdarg (XmNrightAttachment, XmATTACH_FORM); 00681 stdarg (XmNfractionBase, actual_nattrs); 00682 form = XmCreateForm (topform, "attributes", args, n); 00683 XtManageChild (form); 00684 00685 attrcount = -1; 00686 for (i = 0; i < n_attrs; i++) 00687 { 00688 Widget w; 00689 00690 if (attrs[i].help_text == ATTR_UNDOCUMENTED) 00691 continue; 00692 attrcount ++; 00693 00694 n = 0; 00695 stdarg (XmNleftAttachment, XmATTACH_FORM); 00696 stdarg (XmNrightAttachment, XmATTACH_FORM); 00697 stdarg (XmNtopAttachment, XmATTACH_POSITION); 00698 stdarg (XmNtopPosition, attrcount); 00699 stdarg (XmNbottomAttachment, XmATTACH_POSITION); 00700 stdarg (XmNbottomPosition, attrcount + 1); 00701 stdarg (XmNalignment, XmALIGNMENT_END); 00702 w = XmCreateLabel (lform, attrs[i].name, args, n); 00703 XtManageChild (w); 00704 } 00705 00706 attrcount = -1; 00707 for (i = 0; i < n_attrs; i++) 00708 { 00709 static char buf[30]; 00710 n = 0; 00711 00712 if (attrs[i].help_text == ATTR_UNDOCUMENTED) 00713 continue; 00714 attrcount ++; 00715 00716 stdarg (XmNleftAttachment, XmATTACH_FORM); 00717 stdarg (XmNrightAttachment, XmATTACH_FORM); 00718 stdarg (XmNtopAttachment, XmATTACH_POSITION); 00719 stdarg (XmNtopPosition, attrcount); 00720 stdarg (XmNbottomAttachment, XmATTACH_POSITION); 00721 stdarg (XmNbottomPosition, attrcount + 1); 00722 stdarg (XmNalignment, XmALIGNMENT_END); 00723 00724 switch (attrs[i].type) 00725 { 00726 case HID_Label: 00727 stdarg (XmNlabelString, empty); 00728 wl[i] = XmCreateLabel (form, attrs[i].name, args, n); 00729 break; 00730 case HID_Boolean: 00731 stdarg (XmNlabelString, empty); 00732 stdarg (XmNset, results[i].int_value); 00733 wl[i] = XmCreateToggleButton (form, attrs[i].name, args, n); 00734 break; 00735 case HID_String: 00736 stdarg (XmNcolumns, 40); 00737 stdarg (XmNresizeWidth, True); 00738 stdarg (XmNvalue, results[i].str_value); 00739 wl[i] = XmCreateTextField (form, attrs[i].name, args, n); 00740 break; 00741 case HID_Integer: 00742 stdarg (XmNcolumns, 13); 00743 stdarg (XmNresizeWidth, True); 00744 sprintf (buf, "%d", results[i].int_value); 00745 stdarg (XmNvalue, buf); 00746 wl[i] = XmCreateTextField (form, attrs[i].name, args, n); 00747 break; 00748 case HID_Coord: 00749 stdarg (XmNcolumns, 13); 00750 stdarg (XmNresizeWidth, True); 00751 pcb_snprintf (buf, sizeof (buf), "%$mS", results[i].coord_value); 00752 stdarg (XmNvalue, buf); 00753 wl[i] = XmCreateTextField (form, attrs[i].name, args, n); 00754 break; 00755 case HID_Real: 00756 stdarg (XmNcolumns, 16); 00757 stdarg (XmNresizeWidth, True); 00758 sprintf (buf, "%g", results[i].real_value); 00759 stdarg (XmNvalue, buf); 00760 wl[i] = XmCreateTextField (form, attrs[i].name, args, n); 00761 break; 00762 case HID_Enum: 00763 { 00764 static XmString empty = 0; 00765 Widget submenu, default_button=0; 00766 int sn = n; 00767 00768 if (empty == 0) 00769 empty = XmStringCreatePCB (""); 00770 00771 submenu = XmCreatePulldownMenu (form, attrs[i].name, args+sn, n-sn); 00772 00773 n = sn; 00774 stdarg (XmNlabelString, empty); 00775 stdarg (XmNsubMenuId, submenu); 00776 wl[i] = XmCreateOptionMenu (form, attrs[i].name, args, n); 00777 00778 for (sn=0; attrs[i].enumerations[sn]; sn++) 00779 { 00780 Widget btn; 00781 XmString label; 00782 n = 0; 00783 label = XmStringCreatePCB ((char *)attrs[i].enumerations[sn]); 00784 stdarg (XmNuserData, & attrs[i].enumerations[sn]); 00785 stdarg (XmNlabelString, label); 00786 btn = XmCreatePushButton (submenu, "menubutton", args, n); 00787 XtManageChild (btn); 00788 XmStringFree (label); 00789 if (sn == attrs[i].default_val.int_value) 00790 default_button = btn; 00791 } 00792 if (default_button) 00793 { 00794 n = 0; 00795 stdarg (XmNmenuHistory, default_button); 00796 XtSetValues (wl[i], args, n); 00797 } 00798 } 00799 break; 00800 default: 00801 wl[i] = XmCreateLabel (form, "UNIMPLEMENTED", args, n); 00802 break; 00803 } 00804 00805 XtManageChild (wl[i]); 00806 } 00807 00808 rv = wait_for_dialog (dialog); 00809 00810 for (i = 0; i < n_attrs; i++) 00811 { 00812 char *cp; 00813 00814 if (attrs[i].help_text == ATTR_UNDOCUMENTED) 00815 continue; 00816 00817 switch (attrs[i].type) 00818 { 00819 case HID_Boolean: 00820 results[i].int_value = XmToggleButtonGetState (wl[i]); 00821 break; 00822 case HID_String: 00823 results[i].str_value = XmTextGetString (wl[i]); 00824 break; 00825 case HID_Integer: 00826 cp = XmTextGetString (wl[i]); 00827 sscanf (cp, "%d", &results[i].int_value); 00828 break; 00829 case HID_Coord: 00830 cp = XmTextGetString (wl[i]); 00831 results[i].coord_value = GetValue (cp, NULL, NULL); 00832 break; 00833 case HID_Real: 00834 cp = XmTextGetString (wl[i]); 00835 sscanf (cp, "%lg", &results[i].real_value); 00836 break; 00837 case HID_Enum: 00838 { 00839 const char **uptr; 00840 Widget btn; 00841 00842 n = 0; 00843 stdarg (XmNmenuHistory, &btn); 00844 XtGetValues (wl[i], args, n); 00845 n = 0; 00846 stdarg (XmNuserData, &uptr); 00847 XtGetValues (btn, args, n); 00848 results[i].int_value = uptr - attrs[i].enumerations; 00849 } 00850 break; 00851 default: 00852 break; 00853 } 00854 } 00855 00856 free (wl); 00857 XtDestroyWidget (dialog); 00858 00859 return rv ? 0 : 1; 00860 } 00861 00862 /* ------------------------------------------------------------ */ 00863 00864 static const char dowindows_syntax[] = 00865 "DoWindows(1|2|3|4)\n" 00866 "DoWindows(Layout|Library|Log|Netlist)"; 00867 00868 static const char dowindows_help[] = 00869 "Open various GUI windows."; 00870 00871 /* %start-doc actions DoWindows 00872 00873 @table @code 00874 00875 @item 1 00876 @itemx Layout 00877 Open the layout window. Since the layout window is always shown 00878 anyway, this has no effect. 00879 00880 @item 2 00881 @itemx Library 00882 Open the library window. 00883 00884 @item 3 00885 @itemx Log 00886 Open the log window. 00887 00888 @item 4 00889 @itemx Netlist 00890 Open the netlist window. 00891 00892 @end table 00893 00894 %end-doc */ 00895 00896 static int 00897 DoWindows (int argc, char **argv, Coord x, Coord y) 00898 { 00899 const char *a = argc == 1 ? argv[0] : ""; 00900 if (strcmp (a, "1") == 0 || strcasecmp (a, "Layout") == 0) 00901 { 00902 } 00903 else if (strcmp (a, "2") == 0 || strcasecmp (a, "Library") == 0) 00904 { 00905 lesstif_show_library (); 00906 } 00907 else if (strcmp (a, "3") == 0 || strcasecmp (a, "Log") == 0) 00908 { 00909 if (log_form == 0) 00910 lesstif_log (""); 00911 XtManageChild (log_form); 00912 } 00913 else if (strcmp (a, "4") == 0 || strcasecmp (a, "Netlist") == 0) 00914 { 00915 lesstif_show_netlist (); 00916 } 00917 else 00918 { 00919 lesstif_log ("Usage: DoWindows(1|2|3|4|Layout|Library|Log|Netlist)"); 00920 return 1; 00921 } 00922 return 0; 00923 } 00924 00925 /* ------------------------------------------------------------ */ 00926 static const char about_syntax[] = 00927 "About()"; 00928 00929 static const char about_help[] = 00930 "Tell the user about this version of PCB."; 00931 00932 /* %start-doc actions About 00933 00934 This just pops up a dialog telling the user which version of 00935 @code{pcb} they're running. 00936 00937 %end-doc */ 00938 00939 00940 static int 00941 About (int argc, char **argv, Coord x, Coord y) 00942 { 00943 static Widget about = 0; 00944 if (!about) 00945 { 00946 Cardinal n = 0; 00947 XmString xs = XmStringCreatePCB (GetInfoString ()); 00948 stdarg (XmNmessageString, xs); 00949 stdarg (XmNtitle, "About PCB"); 00950 about = XmCreateInformationDialog (mainwind, "about", args, n); 00951 XtUnmanageChild (XmMessageBoxGetChild (about, XmDIALOG_CANCEL_BUTTON)); 00952 XtUnmanageChild (XmMessageBoxGetChild (about, XmDIALOG_HELP_BUTTON)); 00953 } 00954 wait_for_dialog (about); 00955 return 0; 00956 } 00957 00958 /* ------------------------------------------------------------ */ 00959 00960 static const char print_syntax[] = 00961 "Print()"; 00962 00963 static const char print_help[] = 00964 "Print the layout."; 00965 00966 /* %start-doc actions Print 00967 00968 This will find the default printing HID, prompt the user for its 00969 options, and print the layout. 00970 00971 %end-doc */ 00972 00973 static int 00974 Print (int argc, char **argv, Coord x, Coord y) 00975 { 00976 HID_Attribute *opts; 00977 HID *printer; 00978 HID_Attr_Val *vals; 00979 int n; 00980 00981 printer = hid_find_printer (); 00982 if (!printer) 00983 { 00984 lesstif_confirm_dialog ("No printer?", "Oh well", 0); 00985 return 1; 00986 } 00987 opts = printer->get_export_options (&n); 00988 vals = (HID_Attr_Val *) calloc (n, sizeof (HID_Attr_Val)); 00989 if (lesstif_attribute_dialog (opts, n, vals, "Print", "")) 00990 { 00991 free (vals); 00992 return 1; 00993 } 00994 printer->do_export (vals); 00995 free (vals); 00996 return 0; 00997 } 00998 00999 static HID_Attribute 01000 printer_calibrate_attrs[] = { 01001 {"Enter Values here:", "", 01002 HID_Label, 0, 0, {0, 0, 0}, 0, 0}, 01003 {"x-calibration", "X scale for calibrating your printer", 01004 HID_Real, 0.5, 25, {0, 0, 1.00}, 0, 0}, 01005 {"y-calibration", "Y scale for calibrating your printer", 01006 HID_Real, 0.5, 25, {0, 0, 1.00}, 0, 0} 01007 }; 01008 static HID_Attr_Val printer_calibrate_values[3]; 01009 01010 static const char printcalibrate_syntax[] = 01011 "PrintCalibrate()"; 01012 01013 static const char printcalibrate_help[] = 01014 "Calibrate the printer."; 01015 01016 /* %start-doc actions PrintCalibrate 01017 01018 This will print a calibration page, which you would measure and type 01019 the measurements in, so that future printouts will be more precise. 01020 01021 %end-doc */ 01022 01023 static int 01024 PrintCalibrate (int argc, char **argv, Coord x, Coord y) 01025 { 01026 HID *printer = hid_find_printer (); 01027 printer->calibrate (0.0, 0.0); 01028 if (gui->attribute_dialog (printer_calibrate_attrs, 3, 01029 printer_calibrate_values, 01030 "Printer Calibration Values", "Enter calibration values for your printer")) 01031 return 1; 01032 printer->calibrate (printer_calibrate_values[1].real_value, 01033 printer_calibrate_values[2].real_value); 01034 return 0; 01035 } 01036 01037 static const char export_syntax[] = 01038 "Export()"; 01039 01040 static const char export_help[] = 01041 "Export the layout."; 01042 01043 /* %start-doc actions Export 01044 01045 Prompts the user for an exporter to use. Then, prompts the user for 01046 that exporter's options, and exports the layout. 01047 01048 %end-doc */ 01049 01050 static int 01051 Export (int argc, char **argv, Coord x, Coord y) 01052 { 01053 static Widget selector = 0; 01054 HID_Attribute *opts; 01055 HID *printer, **hids; 01056 HID_Attr_Val *vals; 01057 int n, i; 01058 Widget prev = 0; 01059 Widget w; 01060 01061 hids = hid_enumerate (); 01062 01063 if (!selector) 01064 { 01065 n = 0; 01066 stdarg (XmNtitle, "Export HIDs"); 01067 selector = create_form_ok_dialog ("export", 0); 01068 for (i = 0; hids[i]; i++) 01069 { 01070 if (hids[i]->exporter) 01071 { 01072 n = 0; 01073 if (prev) 01074 { 01075 stdarg (XmNtopAttachment, XmATTACH_WIDGET); 01076 stdarg (XmNtopWidget, prev); 01077 } 01078 else 01079 { 01080 stdarg (XmNtopAttachment, XmATTACH_FORM); 01081 } 01082 stdarg (XmNrightAttachment, XmATTACH_FORM); 01083 stdarg (XmNleftAttachment, XmATTACH_FORM); 01084 w = 01085 XmCreatePushButton (selector, (char *) hids[i]->name, args, 01086 n); 01087 XtManageChild (w); 01088 XtAddCallback (w, XmNactivateCallback, 01089 (XtCallbackProc) dialog_callback, 01090 (XtPointer) ((size_t) i + 1)); 01091 prev = w; 01092 } 01093 } 01094 selector = XtParent (selector); 01095 } 01096 01097 i = wait_for_dialog (selector); 01098 01099 if (i <= 0) 01100 return 1; 01101 printer = hids[i - 1]; 01102 01103 exporter = printer; 01104 01105 opts = printer->get_export_options (&n); 01106 vals = (HID_Attr_Val *) calloc (n, sizeof (HID_Attr_Val)); 01107 if (lesstif_attribute_dialog (opts, n, vals, "Export", NULL)) 01108 { 01109 free (vals); 01110 return 1; 01111 } 01112 printer->do_export (vals); 01113 free (vals); 01114 exporter = NULL; 01115 return 0; 01116 } 01117 01118 /* ------------------------------------------------------------ */ 01119 01120 static Widget sizes_dialog = 0; 01121 static Widget sz_pcb_w, sz_pcb_h, sz_bloat, sz_shrink, sz_drc_wid, sz_drc_slk, 01122 sz_drc_drill, sz_drc_ring; 01123 static Widget sz_text; 01124 static Widget sz_set, sz_reset, sz_units; 01125 01126 static int 01127 sz_str2val (Widget w, bool pcbu) 01128 { 01129 char *buf = XmTextGetString (w); 01130 if (!pcbu) 01131 return strtol (buf, NULL, 0); 01132 return GetValueEx (buf, NULL, NULL, NULL, Settings.grid_unit->suffix); 01133 } 01134 01135 static void 01136 sz_val2str (Widget w, Coord u, int pcbu) 01137 { 01138 static char buf[40]; 01139 if (pcbu) 01140 pcb_snprintf (buf, sizeof (buf), "%m+%.2mS", Settings.grid_unit->allow, u); 01141 else 01142 pcb_snprintf (buf, sizeof (buf), "%#mS %%", u); 01143 XmTextSetString (w, buf); 01144 } 01145 01146 static void 01147 sizes_set () 01148 { 01149 PCB->MaxWidth = sz_str2val (sz_pcb_w, 1); 01150 PCB->MaxHeight = sz_str2val (sz_pcb_h, 1); 01151 PCB->Bloat = sz_str2val (sz_bloat, 1); 01152 PCB->Shrink = sz_str2val (sz_shrink, 1); 01153 PCB->minWid = sz_str2val (sz_drc_wid, 1); 01154 PCB->minSlk = sz_str2val (sz_drc_slk, 1); 01155 PCB->minDrill = sz_str2val (sz_drc_drill, 1); 01156 PCB->minRing = sz_str2val (sz_drc_ring, 1); 01157 Settings.TextScale = sz_str2val (sz_text, 0); 01158 01159 Settings.Bloat = PCB->Bloat; 01160 Settings.Shrink = PCB->Shrink; 01161 Settings.minWid = PCB->minWid; 01162 Settings.minSlk = PCB->minSlk; 01163 Settings.minDrill = PCB->minDrill; 01164 Settings.minRing = PCB->minRing; 01165 01166 crosshair_update_range(); 01167 lesstif_pan_fixup (); 01168 } 01169 01170 void 01171 lesstif_sizes_reset () 01172 { 01173 char *ls; 01174 if (!sizes_dialog) 01175 return; 01176 sz_val2str (sz_pcb_w, PCB->MaxWidth, 1); 01177 sz_val2str (sz_pcb_h, PCB->MaxHeight, 1); 01178 sz_val2str (sz_bloat, PCB->Bloat, 1); 01179 sz_val2str (sz_shrink, PCB->Shrink, 1); 01180 sz_val2str (sz_drc_wid, PCB->minWid, 1); 01181 sz_val2str (sz_drc_slk, PCB->minSlk, 1); 01182 sz_val2str (sz_drc_drill, PCB->minDrill, 1); 01183 sz_val2str (sz_drc_ring, PCB->minRing, 1); 01184 sz_val2str (sz_text, Settings.TextScale, 0); 01185 01186 ls = g_strdup_printf (_("Units are %s."), Settings.grid_unit->in_suffix); 01187 n = 0; 01188 stdarg (XmNlabelString, XmStringCreatePCB (ls)); 01189 XtSetValues (sz_units, args, n); 01190 g_free (ls); 01191 } 01192 01193 static Widget 01194 size_field (Widget parent, char *label, int posn) 01195 { 01196 Widget w, l; 01197 n = 0; 01198 stdarg (XmNrightAttachment, XmATTACH_FORM); 01199 stdarg (XmNtopAttachment, XmATTACH_POSITION); 01200 stdarg (XmNtopPosition, posn); 01201 stdarg (XmNbottomAttachment, XmATTACH_POSITION); 01202 stdarg (XmNbottomPosition, posn + 1); 01203 stdarg (XmNcolumns, 10); 01204 w = XmCreateTextField (parent, "field", args, n); 01205 XtManageChild (w); 01206 01207 n = 0; 01208 stdarg (XmNleftAttachment, XmATTACH_FORM); 01209 stdarg (XmNrightAttachment, XmATTACH_WIDGET); 01210 stdarg (XmNrightWidget, w); 01211 stdarg (XmNtopAttachment, XmATTACH_POSITION); 01212 stdarg (XmNtopPosition, posn); 01213 stdarg (XmNbottomAttachment, XmATTACH_POSITION); 01214 stdarg (XmNbottomPosition, posn + 1); 01215 stdarg (XmNlabelString, XmStringCreatePCB (label)); 01216 stdarg (XmNalignment, XmALIGNMENT_END); 01217 l = XmCreateLabel (parent, "label", args, n); 01218 XtManageChild (l); 01219 01220 return w; 01221 } 01222 01223 static const char adjustsizes_syntax[] = 01224 "AdjustSizes()"; 01225 01226 static const char adjustsizes_help[] = 01227 "Let the user change the board size, DRC parameters, etc"; 01228 01229 /* %start-doc actions AdjustSizes 01230 01231 Displays a dialog box that lets the user change the board 01232 size, DRC parameters, and text scale. 01233 01234 The units are determined by the default display units. 01235 01236 %end-doc */ 01237 01238 static int 01239 AdjustSizes (int argc, char **argv, Coord x, Coord y) 01240 { 01241 if (!sizes_dialog) 01242 { 01243 Widget inf, sep; 01244 01245 n = 0; 01246 stdarg (XmNmarginWidth, 3); 01247 stdarg (XmNmarginHeight, 3); 01248 stdarg (XmNhorizontalSpacing, 3); 01249 stdarg (XmNverticalSpacing, 3); 01250 stdarg (XmNautoUnmanage, False); 01251 stdarg (XmNtitle, "Board Sizes"); 01252 sizes_dialog = XmCreateFormDialog (mainwind, "sizes", args, n); 01253 01254 n = 0; 01255 stdarg (XmNrightAttachment, XmATTACH_FORM); 01256 stdarg (XmNbottomAttachment, XmATTACH_FORM); 01257 sz_reset = XmCreatePushButton (sizes_dialog, "Reset", args, n); 01258 XtManageChild (sz_reset); 01259 XtAddCallback (sz_reset, XmNactivateCallback, 01260 (XtCallbackProc) lesstif_sizes_reset, 0); 01261 01262 n = 0; 01263 stdarg (XmNrightAttachment, XmATTACH_WIDGET); 01264 stdarg (XmNrightWidget, sz_reset); 01265 stdarg (XmNbottomAttachment, XmATTACH_FORM); 01266 sz_set = XmCreatePushButton (sizes_dialog, "Set", args, n); 01267 XtManageChild (sz_set); 01268 XtAddCallback (sz_set, XmNactivateCallback, (XtCallbackProc) sizes_set, 01269 0); 01270 01271 n = 0; 01272 stdarg (XmNrightAttachment, XmATTACH_FORM); 01273 stdarg (XmNleftAttachment, XmATTACH_FORM); 01274 stdarg (XmNbottomAttachment, XmATTACH_WIDGET); 01275 stdarg (XmNbottomWidget, sz_reset); 01276 sep = XmCreateSeparator (sizes_dialog, "sep", args, n); 01277 XtManageChild (sep); 01278 01279 n = 0; 01280 stdarg (XmNrightAttachment, XmATTACH_FORM); 01281 stdarg (XmNleftAttachment, XmATTACH_FORM); 01282 stdarg (XmNbottomAttachment, XmATTACH_WIDGET); 01283 stdarg (XmNbottomWidget, sep); 01284 sz_units = XmCreateLabel (sizes_dialog, "units", args, n); 01285 XtManageChild (sz_units); 01286 01287 n = 0; 01288 stdarg (XmNrightAttachment, XmATTACH_FORM); 01289 stdarg (XmNleftAttachment, XmATTACH_FORM); 01290 stdarg (XmNtopAttachment, XmATTACH_FORM); 01291 stdarg (XmNbottomAttachment, XmATTACH_WIDGET); 01292 stdarg (XmNbottomWidget, sz_units); 01293 stdarg (XmNfractionBase, 9); 01294 inf = XmCreateForm (sizes_dialog, "sizes", args, n); 01295 XtManageChild (inf); 01296 01297 sz_pcb_w = size_field (inf, "PCB Width", 0); 01298 sz_pcb_h = size_field (inf, "PCB Height", 1); 01299 sz_bloat = size_field (inf, "Bloat", 2); 01300 sz_shrink = size_field (inf, "Shrink", 3); 01301 sz_drc_wid = size_field (inf, "DRC Min Wid", 4); 01302 sz_drc_slk = size_field (inf, "DRC Min Silk", 5); 01303 sz_drc_drill = size_field (inf, "DRC Min Drill", 6); 01304 sz_drc_ring = size_field (inf, "DRC Min Annular Ring", 7); 01305 sz_text = size_field (inf, "Text Scale", 8); 01306 } 01307 lesstif_sizes_reset (); 01308 XtManageChild (sizes_dialog); 01309 return 0; 01310 } 01311 01312 /* ------------------------------------------------------------ */ 01313 01314 static Widget layer_groups_form = 0; 01315 static Widget lg_buttonform = 0; 01316 01317 static int lg_setcol[MAX_ALL_LAYER]; 01318 static int lg_width, lg_height; 01319 static int lg_r[MAX_ALL_LAYER + 1]; 01320 static int lg_c[MAX_ALL_LAYER + 1]; 01321 static int lg_label_width, lg_fa, lg_fd; 01322 static GC lg_gc = 0; 01323 01324 #if 0 01325 static Widget lglabels[MAX_ALL_LAYER]; 01326 static Widget lgbuttons[MAX_ALL_LAYER][MAX_GROUP]; 01327 #endif 01328 01329 typedef struct { 01330 XFontStruct *font; 01331 Pixel fg, bg, sel; 01332 } LgResource; 01333 01334 static LgResource lgr; 01335 01336 static XtResource lg_resources[] = { 01337 { "font", "Font", XtRFontStruct, sizeof(XFontStruct*), XtOffset(LgResource*, font), XtRString, (void *)"fixed" }, 01338 { "foreground", "Foreground", XtRPixel, sizeof(Pixel), XtOffset(LgResource*, fg), XtRString, (void *)"black" }, 01339 { "selectColor", "Foreground", XtRPixel, sizeof(Pixel), XtOffset(LgResource*, sel), XtRString, (void *)"blue" }, 01340 { "background", "Background", XtRPixel, sizeof(Pixel), XtOffset(LgResource*, bg), XtRString, (void *)"white" } 01341 }; 01342 01343 #if 0 01344 static void 01345 lgbutton_cb (Widget w, int ij, void *cbs) 01346 { 01347 int layer, group, k; 01348 01349 layer = ij / max_group; 01350 group = ij % max_group; 01351 group = MoveLayerToGroup (layer, group); 01352 for (k = 0; k < max_group; k++) 01353 { 01354 if (k == group) 01355 XmToggleButtonSetState (lgbuttons[layer][k], 1, 0); 01356 else 01357 XmToggleButtonSetState (lgbuttons[layer][k], 0, 0); 01358 } 01359 } 01360 #endif 01361 01362 static void 01363 lgbutton_expose (Widget w, XtPointer u, XmDrawingAreaCallbackStruct *cbs) 01364 { 01365 int i; 01366 Window win = XtWindow(w); 01367 01368 if (cbs && cbs->event->xexpose.count) 01369 return; 01370 if (lg_gc == 0 && !cbs) 01371 return; 01372 if (lg_gc == 0 && cbs) 01373 { 01374 lg_gc = XCreateGC (display, win, 0, 0); 01375 XSetFont (display, lg_gc, lgr.font->fid); 01376 } 01377 01378 XSetForeground (display, lg_gc, lgr.bg); 01379 XFillRectangle (display, win, lg_gc, 0, 0, lg_width, lg_height); 01380 XSetForeground (display, lg_gc, lgr.fg); 01381 for (i = 0; i < max_group; i++) 01382 XDrawLine(display, win, lg_gc, lg_c[i], 0, lg_c[i], lg_height); 01383 for (i = 1; i < max_copper_layer + SILK_LAYER; i++) 01384 XDrawLine(display, win, lg_gc, lg_label_width, lg_r[i], lg_width, lg_r[i]); 01385 for (i = 0; i < max_copper_layer + SILK_LAYER; i++) 01386 { 01387 int dir; 01388 XCharStruct size; 01389 int swidth; 01390 const char *name; 01391 01392 if (i == bottom_silk_layer) 01393 name = BOTTOM_SIDE_NAME; 01394 else if (i == top_silk_layer) 01395 name = TOP_SIDE_NAME; 01396 else 01397 name = PCB->Data->Layer[i].Name; 01398 XTextExtents (lgr.font, name, strlen(name), &dir, &lg_fa, &lg_fd, &size); 01399 swidth = size.rbearing - size.lbearing; 01400 XDrawString(display, win, lg_gc, 01401 (lg_label_width - swidth)/2 - size.lbearing, 01402 (lg_r[i] + lg_r[i+1] + lg_fd + lg_fa)/2 - 1, 01403 name, strlen(name)); 01404 } 01405 XSetForeground (display, lg_gc, lgr.sel); 01406 for (i = 0; i < max_copper_layer + SILK_LAYER; i++) 01407 { 01408 int c = lg_setcol[i]; 01409 int x1 = lg_c[c] + 2; 01410 int x2 = lg_c[c+1] - 2; 01411 int y1 = lg_r[i] + 2; 01412 int y2 = lg_r[i+1] - 2; 01413 XFillRectangle (display, win, lg_gc, x1, y1, x2-x1+1, y2-y1+1); 01414 } 01415 } 01416 01417 static void 01418 lgbutton_input (Widget w, XtPointer u, XmDrawingAreaCallbackStruct *cbs) 01419 { 01420 int layer, group; 01421 if (cbs->event->type != ButtonPress) 01422 return; 01423 layer = cbs->event->xbutton.y * (max_copper_layer + SILK_LAYER) / 01424 lg_height; 01425 group = (cbs->event->xbutton.x - lg_label_width) * max_group / (lg_width - lg_label_width); 01426 group = MoveLayerToGroup (layer, group); 01427 lg_setcol[layer] = group; 01428 lgbutton_expose (w, 0, 0); 01429 gui->invalidate_all (); 01430 } 01431 01432 static void 01433 lgbutton_resize (Widget w, XtPointer u, XmDrawingAreaCallbackStruct *cbs) 01434 { 01435 int i; 01436 Dimension width, height; 01437 n = 0; 01438 stdarg(XmNwidth, &width); 01439 stdarg(XmNheight, &height); 01440 XtGetValues(w, args, n); 01441 lg_width = width; 01442 lg_height = height; 01443 01444 for (i=0; i<=max_group; i++) 01445 lg_c[i] = lg_label_width + (lg_width - lg_label_width) * i / max_group; 01446 for (i=0; i<=max_copper_layer + SILK_LAYER; i++) 01447 lg_r[i] = lg_height * i / (max_copper_layer + SILK_LAYER); 01448 lgbutton_expose (w, 0, 0); 01449 } 01450 01451 void 01452 lesstif_update_layer_groups () 01453 { 01454 int sets[MAX_ALL_LAYER][MAX_GROUP]; 01455 int i, j, n; 01456 LayerGroupType *l = &(PCB->LayerGroups); 01457 01458 if (!layer_groups_form) 01459 return; 01460 01461 memset (sets, 0, sizeof (sets)); 01462 01463 for (i = 0; i < max_group; i++) 01464 for (j = 0; j < l->Number[i]; j++) 01465 { 01466 sets[l->Entries[i][j]][i] = 1; 01467 lg_setcol[l->Entries[i][j]] = i; 01468 } 01469 01470 lg_label_width = 0; 01471 for (i = 0; i < max_copper_layer + SILK_LAYER; i++) 01472 { 01473 int dir; 01474 XCharStruct size; 01475 int swidth; 01476 const char *name; 01477 01478 if (i == bottom_silk_layer) 01479 name = BOTTOM_SIDE_NAME; 01480 else if (i == top_silk_layer) 01481 name = TOP_SIDE_NAME; 01482 else 01483 name = PCB->Data->Layer[i].Name; 01484 XTextExtents (lgr.font, name, strlen(name), &dir, &lg_fa, &lg_fd, &size); 01485 swidth = size.rbearing - size.lbearing; 01486 if (lg_label_width < swidth) 01487 lg_label_width = swidth; 01488 } 01489 lg_label_width += 4; 01490 01491 n = 0; 01492 stdarg(XmNwidth, lg_label_width + (lg_fa+lg_fd) * max_group); 01493 stdarg(XmNheight, (lg_fa+lg_fd) * (max_copper_layer + SILK_LAYER)); 01494 XtSetValues(lg_buttonform, args, n); 01495 lgbutton_expose (lg_buttonform, 0, 0); 01496 01497 #if 0 01498 for (i = 0; i < max_copper_layer + SILK_LAYER; i++) 01499 { 01500 char *name = "unknown"; 01501 n = 0; 01502 if (i < max_copper_layer) 01503 name = PCB->Data->Layer[i].Name; 01504 else if (i == bottom_silk_layer) 01505 name = BOTTOM_SIDE_NAME; 01506 else if (i == top_silk_layer) 01507 name = TOP_SIDE_NAME; 01508 stdarg (XmNlabelString, XmStringCreatePCB (name)); 01509 XtSetValues (lglabels[i], args, n); 01510 for (j = 0; j < max_group; j++) 01511 { 01512 if (sets[i][j] != XmToggleButtonGetState (lgbuttons[i][j])) 01513 { 01514 XmToggleButtonSetState (lgbuttons[i][j], sets[i][j], 0); 01515 } 01516 } 01517 } 01518 XtUnmanageChild(lg_buttonform); 01519 for (i = 0; i < MAX_ALL_LAYER; i++) 01520 for (j = 0; j < MAX_GROUP; j++) 01521 { 01522 if (i < max_copper_layer + SILK_LAYER && j < max_group) 01523 { 01524 XtManageChild(lgbuttons[i][j]); 01525 n = 0; 01526 stdarg (XmNleftPosition, j * (max_copper_layer + SILK_LAYER)); 01527 stdarg (XmNrightPosition, (j + 1) * (max_copper_layer + SILK_LAYER)); 01528 stdarg (XmNtopPosition, i * max_group); 01529 stdarg (XmNbottomPosition, (i + 1) * max_group); 01530 XtSetValues(lgbuttons[i][j], args, n); 01531 } 01532 else 01533 XtUnmanageChild(lgbuttons[i][j]); 01534 } 01535 n = 0; 01536 stdarg (XmNfractionBase, max_copper_layer + SILK_LAYER); 01537 XtSetValues (layer_groups_form, args, n); 01538 n = 0; 01539 stdarg (XmNfractionBase, max_group * (max_copper_layer + SILK_LAYER)); 01540 XtSetValues (lg_buttonform, args, n); 01541 XtManageChild(lg_buttonform); 01542 #endif 01543 } 01544 01545 static const char editlayergroups_syntax[] = 01546 "EditLayerGroups()"; 01547 01548 static const char editlayergroups_help[] = 01549 "Let the user change the layer groupings"; 01550 01551 /* %start-doc actions EditLayerGroups 01552 01553 Displays a dialog that lets the user view and change the layer 01554 groupings. Each layer (row) can be a member of any one layer group 01555 (column). Note the special layers @code{solder} and @code{component} 01556 allow you to specify which groups represent the top and bottom of the 01557 board. 01558 01559 See @ref{ChangeName Action}. 01560 01561 %end-doc */ 01562 01563 static int 01564 EditLayerGroups (int argc, char **argv, Coord x, Coord y) 01565 { 01566 if (!layer_groups_form) 01567 { 01568 01569 n = 0; 01570 stdarg (XmNfractionBase, max_copper_layer + SILK_LAYER); 01571 stdarg (XmNtitle, "Layer Groups"); 01572 layer_groups_form = XmCreateFormDialog (mainwind, "layers", args, n); 01573 01574 n = 0; 01575 stdarg (XmNtopAttachment, XmATTACH_FORM); 01576 stdarg (XmNbottomAttachment, XmATTACH_FORM); 01577 stdarg (XmNrightAttachment, XmATTACH_FORM); 01578 stdarg (XmNleftAttachment, XmATTACH_FORM); 01579 lg_buttonform = XmCreateDrawingArea (layer_groups_form, "layers", args, n); 01580 XtManageChild (lg_buttonform); 01581 01582 XtAddCallback (lg_buttonform, XmNexposeCallback, 01583 (XtCallbackProc) lgbutton_expose, 0); 01584 XtAddCallback (lg_buttonform, XmNinputCallback, 01585 (XtCallbackProc) lgbutton_input, 0); 01586 XtAddCallback (lg_buttonform, XmNresizeCallback, 01587 (XtCallbackProc) lgbutton_resize, 0); 01588 01589 XtGetSubresources (layer_groups_form, &lgr, 01590 "layergroups", "LayerGroups", 01591 lg_resources, XtNumber(lg_resources), 0, 0); 01592 #if 0 01593 stdarg (XmNfractionBase, max_group * (MAX_ALL_LAYER)); 01594 lg_buttonform = XmCreateForm (layer_groups_form, "lgbutton", args, n); 01595 01596 for (i = 0; i < MAX_ALL_LAYER; i++) 01597 { 01598 n = 0; 01599 stdarg (XmNleftAttachment, XmATTACH_FORM); 01600 stdarg (XmNtopAttachment, XmATTACH_POSITION); 01601 stdarg (XmNtopPosition, i); 01602 stdarg (XmNbottomAttachment, XmATTACH_POSITION); 01603 stdarg (XmNbottomPosition, i + 1); 01604 stdarg (XmNrightAttachment, XmATTACH_WIDGET); 01605 stdarg (XmNrightWidget, lg_buttonform); 01606 lglabels[i] = XmCreateLabel (layer_groups_form, "layer", args, n); 01607 XtManageChild (lglabels[i]); 01608 01609 for (j = 0; j < MAX_GROUP; j++) 01610 { 01611 n = 0; 01612 stdarg (XmNleftAttachment, XmATTACH_POSITION); 01613 stdarg (XmNleftPosition, j * (MAX_LAYER)); 01614 stdarg (XmNrightAttachment, XmATTACH_POSITION); 01615 stdarg (XmNrightPosition, (j + 1) * (MAX_LAYER)); 01616 stdarg (XmNtopAttachment, XmATTACH_POSITION); 01617 stdarg (XmNtopPosition, i * MAX_LAYER); 01618 stdarg (XmNbottomAttachment, XmATTACH_POSITION); 01619 stdarg (XmNbottomPosition, (i + 1) * MAX_LAYER); 01620 stdarg (XmNlabelString, XmStringCreatePCB (" ")); 01621 stdarg (XmNspacing, 0); 01622 stdarg (XmNvisibleWhenOff, True); 01623 stdarg (XmNfillOnSelect, True); 01624 stdarg (XmNshadowThickness, 0); 01625 stdarg (XmNmarginWidth, 0); 01626 stdarg (XmNmarginHeight, 0); 01627 stdarg (XmNhighlightThickness, 0); 01628 lgbuttons[i][j] = 01629 XmCreateToggleButton (lg_buttonform, "label", args, n); 01630 XtManageChild (lgbuttons[i][j]); 01631 01632 XtAddCallback (lgbuttons[i][j], XmNvalueChangedCallback, 01633 (XtCallbackProc) lgbutton_cb, 01634 (XtPointer) (i * max_group + j)); 01635 } 01636 } 01637 #endif 01638 } 01639 lesstif_update_layer_groups (); 01640 XtManageChild (layer_groups_form); 01641 return 1; 01642 } 01643 01644 /* ------------------------------------------------------------ */ 01645 01646 typedef struct { 01647 Widget del; 01648 Widget w_name; 01649 Widget w_value; 01650 } AttrRow; 01651 01652 static AttrRow *attr_row = 0; 01653 static int attr_num_rows = 0; 01654 static int attr_max_rows = 0; 01655 static Widget attr_dialog = NULL, f_top; 01656 static AttributeListType *attributes_list; 01657 01658 static void attributes_delete_callback (Widget w, void *v, void *cbs); 01659 01660 static void 01661 fiddle_with_bb_layout () 01662 { 01663 int i; 01664 int max_height = 0; 01665 int max_del_width = 0; 01666 int max_name_width = 0; 01667 int max_value_width = 0; 01668 short ncolumns = 20; 01669 short vcolumns = 20; 01670 01671 for (i=0; i<attr_num_rows; i++) 01672 { 01673 String v; 01674 01675 n = 0; 01676 stdarg (XmNvalue, &v); 01677 XtGetValues (attr_row[i].w_name, args, n); 01678 if (ncolumns < strlen (v)) 01679 ncolumns = strlen (v); 01680 01681 n = 0; 01682 stdarg (XmNvalue, &v); 01683 XtGetValues (attr_row[i].w_value, args, n); 01684 if (vcolumns < strlen (v)) 01685 vcolumns = strlen (v); 01686 } 01687 01688 for (i=0; i<attr_num_rows; i++) 01689 { 01690 n = 0; 01691 stdarg (XmNcolumns, ncolumns); 01692 XtSetValues (attr_row[i].w_name, args, n); 01693 01694 n = 0; 01695 stdarg (XmNcolumns, vcolumns); 01696 XtSetValues (attr_row[i].w_value, args, n); 01697 } 01698 01699 for (i=0; i<attr_num_rows; i++) 01700 { 01701 Dimension w, h; 01702 n = 0; 01703 stdarg (XmNwidth, &w); 01704 stdarg (XmNheight, &h); 01705 01706 XtGetValues (attr_row[i].del, args, n); 01707 if (max_height < h) 01708 max_height = h; 01709 if (max_del_width < w) 01710 max_del_width = w; 01711 01712 XtGetValues (attr_row[i].w_name, args, n); 01713 if (max_height < h) 01714 max_height = h; 01715 if (max_name_width < w) 01716 max_name_width = w; 01717 01718 XtGetValues (attr_row[i].w_value, args, n); 01719 if (max_height < h) 01720 max_height = h; 01721 if (max_value_width < w) 01722 max_value_width = w; 01723 } 01724 01725 for (i=0; i<attr_num_rows; i++) 01726 { 01727 n = 0; 01728 stdarg (XmNx, 0); 01729 stdarg (XmNy, i * max_height); 01730 stdarg (XmNwidth, max_del_width); 01731 stdarg (XmNheight, max_height); 01732 XtSetValues (attr_row[i].del, args, n); 01733 01734 n = 0; 01735 stdarg (XmNx, max_del_width); 01736 stdarg (XmNy, i * max_height); 01737 stdarg (XmNwidth, max_name_width); 01738 stdarg (XmNheight, max_height); 01739 XtSetValues (attr_row[i].w_name, args, n); 01740 01741 n = 0; 01742 stdarg (XmNx, max_del_width + max_name_width); 01743 stdarg (XmNy, i * max_height); 01744 stdarg (XmNwidth, max_value_width); 01745 stdarg (XmNheight, max_height); 01746 XtSetValues (attr_row[i].w_value, args, n); 01747 } 01748 01749 n = 0; 01750 stdarg (XmNwidth, max_del_width + max_name_width + max_value_width + 1); 01751 stdarg (XmNheight, max_height * attr_num_rows + 1); 01752 XtSetValues (f_top, args, n); 01753 } 01754 01755 static void 01756 lesstif_attributes_need_rows (int new_max) 01757 { 01758 if (attr_max_rows < new_max) 01759 { 01760 if (attr_row) 01761 attr_row = (AttrRow *) realloc (attr_row, new_max * sizeof(AttrRow)); 01762 else 01763 attr_row = (AttrRow *) malloc (new_max * sizeof(AttrRow)); 01764 } 01765 01766 while (attr_max_rows < new_max) 01767 { 01768 n = 0; 01769 attr_row[attr_max_rows].del = XmCreatePushButton (f_top, "del", args, n); 01770 XtManageChild (attr_row[attr_max_rows].del); 01771 XtAddCallback (attr_row[attr_max_rows].del, XmNactivateCallback, 01772 (XtCallbackProc) attributes_delete_callback, 01773 (XtPointer) (size_t) attr_max_rows); 01774 01775 n = 0; 01776 stdarg (XmNresizeWidth, True); 01777 attr_row[attr_max_rows].w_name = XmCreateTextField (f_top, "name", args, n); 01778 XtManageChild (attr_row[attr_max_rows].w_name); 01779 XtAddCallback (attr_row[attr_max_rows].w_name, XmNvalueChangedCallback, 01780 (XtCallbackProc) fiddle_with_bb_layout, NULL); 01781 01782 n = 0; 01783 stdarg (XmNresizeWidth, True); 01784 attr_row[attr_max_rows].w_value = XmCreateTextField (f_top, "value", args, n); 01785 XtManageChild (attr_row[attr_max_rows].w_value); 01786 XtAddCallback (attr_row[attr_max_rows].w_value, XmNvalueChangedCallback, 01787 (XtCallbackProc) fiddle_with_bb_layout, NULL); 01788 01789 attr_max_rows ++; 01790 } 01791 01792 /* Manage any previously unused rows we now need to show. */ 01793 while (attr_num_rows < new_max) 01794 { 01795 XtManageChild (attr_row[attr_num_rows].del); 01796 XtManageChild (attr_row[attr_num_rows].w_name); 01797 XtManageChild (attr_row[attr_num_rows].w_value); 01798 attr_num_rows ++; 01799 } 01800 } 01801 01802 static void 01803 lesstif_attributes_revert () 01804 { 01805 int i; 01806 01807 lesstif_attributes_need_rows (attributes_list->Number); 01808 01809 /* Unmanage any previously used rows we don't need. */ 01810 while (attr_num_rows > attributes_list->Number) 01811 { 01812 attr_num_rows --; 01813 XtUnmanageChild (attr_row[attr_num_rows].del); 01814 XtUnmanageChild (attr_row[attr_num_rows].w_name); 01815 XtUnmanageChild (attr_row[attr_num_rows].w_value); 01816 } 01817 01818 /* Fill in values */ 01819 for (i=0; i<attributes_list->Number; i++) 01820 { 01821 XmTextFieldSetString (attr_row[i].w_name, attributes_list->List[i].name); 01822 XmTextFieldSetString (attr_row[i].w_value, attributes_list->List[i].value); 01823 } 01824 01825 fiddle_with_bb_layout (); 01826 } 01827 01828 static void 01829 attributes_new_callback (Widget w, void *v, void *cbs) 01830 { 01831 lesstif_attributes_need_rows (attr_num_rows + 1); /* also bumps attr_num_rows */ 01832 XmTextFieldSetString (attr_row[attr_num_rows-1].w_name, ""); 01833 XmTextFieldSetString (attr_row[attr_num_rows-1].w_value, ""); 01834 01835 fiddle_with_bb_layout (); 01836 } 01837 01838 static void 01839 attributes_delete_callback (Widget w, void *v, void *cbs) 01840 { 01841 int i, n; 01842 Widget wn, wv; 01843 01844 n = (int) (size_t) v; 01845 01846 wn = attr_row[n].w_name; 01847 wv = attr_row[n].w_value; 01848 01849 for (i=n; i<attr_num_rows-1; i++) 01850 { 01851 attr_row[i].w_name = attr_row[i+1].w_name; 01852 attr_row[i].w_value = attr_row[i+1].w_value; 01853 } 01854 attr_row[attr_num_rows-1].w_name = wn; 01855 attr_row[attr_num_rows-1].w_value = wv; 01856 attr_num_rows --; 01857 01858 XtUnmanageChild (wn); 01859 XtUnmanageChild (wv); 01860 01861 fiddle_with_bb_layout (); 01862 } 01863 01864 static void 01865 attributes_revert_callback (Widget w, void *v, void *cbs) 01866 { 01867 lesstif_attributes_revert (); 01868 } 01869 01870 void 01871 lesstif_attributes_dialog (char *owner, AttributeListType *attrs_list) 01872 { 01873 Widget bform, sw, b_ok, b_cancel, b_revert, b_new; 01874 Widget sep; 01875 01876 if (attr_dialog == NULL) 01877 { 01878 n = 0; 01879 stdarg (XmNautoUnmanage, False); 01880 stdarg (XmNtitle, owner); 01881 stdarg (XmNwidth, 400); 01882 stdarg (XmNheight, 300); 01883 attr_dialog = XmCreateFormDialog (mainwind, "attributes", args, n); 01884 01885 n = 0; 01886 stdarg (XmNrightAttachment, XmATTACH_FORM); 01887 stdarg (XmNbottomAttachment, XmATTACH_FORM); 01888 stdarg (XmNorientation, XmHORIZONTAL); 01889 stdarg (XmNentryAlignment, XmALIGNMENT_CENTER); 01890 stdarg (XmNpacking, XmPACK_COLUMN); 01891 bform = XmCreateRowColumn (attr_dialog, "attributes", args, n); 01892 XtManageChild (bform); 01893 01894 n = 0; 01895 b_ok = XmCreatePushButton (bform, "OK", args, n); 01896 XtManageChild (b_ok); 01897 XtAddCallback (b_ok, XmNactivateCallback, 01898 (XtCallbackProc) dialog_callback, 01899 (XtPointer) 0); 01900 01901 n = 0; 01902 b_new = XmCreatePushButton (bform, "New", args, n); 01903 XtManageChild (b_new); 01904 XtAddCallback (b_new, XmNactivateCallback, 01905 (XtCallbackProc) attributes_new_callback, 01906 NULL); 01907 01908 n = 0; 01909 b_revert = XmCreatePushButton (bform, "Revert", args, n); 01910 XtManageChild (b_revert); 01911 XtAddCallback (b_revert, XmNactivateCallback, 01912 (XtCallbackProc) attributes_revert_callback, 01913 NULL); 01914 01915 n = 0; 01916 b_cancel = XmCreatePushButton (bform, "Cancel", args, n); 01917 XtManageChild (b_cancel); 01918 XtAddCallback (b_cancel, XmNactivateCallback, 01919 (XtCallbackProc) dialog_callback, 01920 (XtPointer) 1); 01921 01922 n = 0; 01923 stdarg (XmNleftAttachment, XmATTACH_FORM); 01924 stdarg (XmNrightAttachment, XmATTACH_FORM); 01925 stdarg (XmNbottomAttachment, XmATTACH_WIDGET); 01926 stdarg (XmNbottomWidget, bform); 01927 sep = XmCreateSeparator (attr_dialog, "attributes", args, n); 01928 XtManageChild (sep); 01929 01930 n = 0; 01931 stdarg (XmNtopAttachment, XmATTACH_FORM); 01932 stdarg (XmNleftAttachment, XmATTACH_FORM); 01933 stdarg (XmNrightAttachment, XmATTACH_FORM); 01934 stdarg (XmNbottomAttachment, XmATTACH_WIDGET); 01935 stdarg (XmNbottomWidget, sep); 01936 stdarg (XmNscrollingPolicy, XmAUTOMATIC); 01937 sw = XmCreateScrolledWindow (attr_dialog, "attributes", args, n); 01938 XtManageChild (sw); 01939 01940 n = 0; 01941 stdarg (XmNmarginHeight, 0); 01942 stdarg (XmNmarginWidth, 0); 01943 f_top = XmCreateBulletinBoard (sw, "f_top", args, n); 01944 XtManageChild (f_top); 01945 } 01946 else 01947 { 01948 n = 0; 01949 stdarg (XmNtitle, owner); 01950 XtSetValues (XtParent (attr_dialog), args, n); 01951 } 01952 01953 attributes_list = attrs_list; 01954 lesstif_attributes_revert (); 01955 01956 fiddle_with_bb_layout (); 01957 01958 if (wait_for_dialog (attr_dialog) == 0) 01959 { 01960 int i; 01961 /* Copy the values back */ 01962 for (i=0; i<attributes_list->Number; i++) 01963 { 01964 if (attributes_list->List[i].name) 01965 free (attributes_list->List[i].name); 01966 if (attributes_list->List[i].value) 01967 free (attributes_list->List[i].value); 01968 } 01969 if (attributes_list->Max < attr_num_rows) 01970 { 01971 int sz = attr_num_rows * sizeof (AttributeType); 01972 if (attributes_list->List == NULL) 01973 attributes_list->List = (AttributeType *) malloc (sz); 01974 else 01975 attributes_list->List = (AttributeType *) realloc (attributes_list->List, sz); 01976 attributes_list->Max = attr_num_rows; 01977 } 01978 for (i=0; i<attr_num_rows; i++) 01979 { 01980 attributes_list->List[i].name = strdup (XmTextFieldGetString (attr_row[i].w_name)); 01981 attributes_list->List[i].value = strdup (XmTextFieldGetString (attr_row[i].w_value)); 01982 attributes_list->Number = attr_num_rows; 01983 } 01984 } 01985 01986 return; 01987 } 01988 01989 /* ------------------------------------------------------------ */ 01990 01991 static const char importgui_syntax[] = 01992 "ImportGUI()"; 01993 01994 static const char importgui_help[] = 01995 "Lets the user choose the schematics to import from"; 01996 01997 /* %start-doc actions ImportGUI 01998 01999 Displays a dialog that lets the user select the schematic(s) to import 02000 from, then saves that information in the layout's attributes for 02001 future imports. 02002 02003 %end-doc */ 02004 02005 static int 02006 ImportGUI (int argc, char **argv, Coord x, Coord y) 02007 { 02008 static int I_am_recursing = 0; 02009 static XmString xms_sch = 0, xms_import = 0; 02010 int rv; 02011 XmString xmname; 02012 char *name, *bname; 02013 char *original_dir, *target_dir, *last_slash; 02014 02015 if (I_am_recursing) 02016 return 1; 02017 02018 if (xms_sch == 0) 02019 xms_sch = XmStringCreatePCB ("*.sch"); 02020 if (xms_import == 0) 02021 xms_import = XmStringCreatePCB ("Import from"); 02022 02023 setup_fsb_dialog (); 02024 02025 n = 0; 02026 stdarg (XmNtitle, "Import From"); 02027 XtSetValues (XtParent (fsb), args, n); 02028 02029 n = 0; 02030 stdarg (XmNpattern, xms_sch); 02031 stdarg (XmNmustMatch, True); 02032 stdarg (XmNselectionLabelString, xms_import); 02033 XtSetValues (fsb, args, n); 02034 02035 n = 0; 02036 stdarg (XmNdirectory, &xmname); 02037 XtGetValues (fsb, args, n); 02038 XmStringGetLtoR (xmname, XmFONTLIST_DEFAULT_TAG, &original_dir); 02039 02040 if (!wait_for_dialog (fsb)) 02041 return 1; 02042 02043 n = 0; 02044 stdarg (XmNdirectory, &xmname); 02045 XtGetValues (fsb, args, n); 02046 XmStringGetLtoR (xmname, XmFONTLIST_DEFAULT_TAG, &target_dir); 02047 02048 n = 0; 02049 stdarg (XmNdirSpec, &xmname); 02050 XtGetValues (fsb, args, n); 02051 02052 XmStringGetLtoR (xmname, XmFONTLIST_DEFAULT_TAG, &name); 02053 02054 /* If the user didn't change directories, use just the base name. 02055 This is the common case and means we don't have to get clever 02056 about converting absolute paths into relative paths. */ 02057 bname = name; 02058 if (strcmp (original_dir, target_dir) == 0) 02059 { 02060 last_slash = strrchr (name, '/'); 02061 if (last_slash) 02062 bname = last_slash + 1; 02063 } 02064 02065 AttributePut (PCB, "import::src0", bname); 02066 02067 XtFree (name); 02068 02069 02070 I_am_recursing = 1; 02071 rv = hid_action ("Import"); 02072 I_am_recursing = 0; 02073 02074 return rv; 02075 } 02076 02077 /* ------------------------------------------------------------ */ 02078 02079 HID_Action lesstif_dialog_action_list[] = { 02080 {"Load", 0, Load, 02081 load_help, load_syntax}, 02082 {"LoadVendor", 0, LoadVendor, 02083 loadvendor_help, loadvendor_syntax}, 02084 {"Save", 0, Save, 02085 save_help, save_syntax}, 02086 {"DoWindows", 0, DoWindows, 02087 dowindows_help, dowindows_syntax}, 02088 {"PromptFor", 0, PromptFor, 02089 promptfor_help, promptfor_syntax}, 02090 {"Confirm", 0, ConfirmAction}, 02091 {"About", 0, About, 02092 about_help, about_syntax}, 02093 {"Print", 0, Print, 02094 print_help, print_syntax}, 02095 {"PrintCalibrate", 0, PrintCalibrate, 02096 printcalibrate_help, printcalibrate_syntax}, 02097 {"Export", 0, Export, 02098 export_help, export_syntax}, 02099 {"AdjustSizes", 0, AdjustSizes, 02100 adjustsizes_help, adjustsizes_syntax}, 02101 {"EditLayerGroups", 0, EditLayerGroups, 02102 editlayergroups_help, editlayergroups_syntax}, 02103 {"ImportGUI", 0, ImportGUI, 02104 importgui_help, importgui_syntax}, 02105 }; 02106 02107 REGISTER_ACTIONS (lesstif_dialog_action_list)