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 00016 #include "find.h" 00017 #include "rats.h" 00018 #include "select.h" 00019 #include "undo.h" 00020 #include "remove.h" 00021 #include "crosshair.h" 00022 #include "draw.h" 00023 00024 #include "hid.h" 00025 #include "../hidint.h" 00026 #include "lesstif.h" 00027 00028 #ifdef HAVE_LIBDMALLOC 00029 #include <dmalloc.h> 00030 #endif 00031 00032 static Arg args[30]; 00033 static int n; 00034 #define stdarg(t,v) XtSetArg(args[n], t, v); n++ 00035 00036 static Widget netlist_dialog = 0; 00037 static Widget netlist_list, netnode_list; 00038 00039 static XmString *netlist_strings = 0; 00040 static XmString *netnode_strings = 0; 00041 static int n_netnode_strings; 00042 static int last_pick = -1; 00043 00044 static int LesstifNetlistChanged (int argc, char **argv, Coord x, Coord y); 00045 00046 static void 00047 pick_net (int pick) 00048 { 00049 LibraryMenuType *menu = PCB->NetlistLib.Menu + pick; 00050 int i; 00051 00052 if (pick == last_pick) 00053 return; 00054 last_pick = pick; 00055 00056 if (netnode_strings) 00057 free (netnode_strings); /* XXX leaked all XmStrings??? */ 00058 n_netnode_strings = menu->EntryN; 00059 netnode_strings = (XmString *) malloc (menu->EntryN * sizeof (XmString)); 00060 for (i = 0; i < menu->EntryN; i++) 00061 netnode_strings[i] = XmStringCreatePCB (menu->Entry[i].ListEntry); 00062 n = 0; 00063 stdarg (XmNitems, netnode_strings); 00064 stdarg (XmNitemCount, menu->EntryN); 00065 XtSetValues (netnode_list, args, n); 00066 } 00067 00068 static void 00069 netlist_select (Widget w, void *v, XmListCallbackStruct * cbs) 00070 { 00071 XmString str; 00072 int pos = cbs->item_position; 00073 LibraryMenuType *net = & (PCB->NetlistLib.Menu[pos - 1]); 00074 char *name = net->Name; 00075 if (name[0] == ' ') 00076 { 00077 name[0] = '*'; 00078 net->flag = 0; 00079 } 00080 else 00081 { 00082 name[0] = ' '; 00083 net->flag = 1; 00084 } 00085 00086 str = XmStringCreatePCB (name); 00087 XmListReplaceItemsPos (netlist_list, &str, 1, pos); 00088 XmStringFree (str); 00089 XmListSelectPos (netlist_list, pos, False); 00090 } 00091 00092 static void 00093 netlist_extend (Widget w, void *v, XmListCallbackStruct * cbs) 00094 { 00095 if (cbs->selected_item_count == 1) 00096 pick_net (cbs->item_position - 1); 00097 } 00098 00099 typedef void (*Std_Nbcb_Func)(LibraryMenuType *, int); 00100 00101 static void 00102 nbcb_rat_on (LibraryMenuType *net, int pos) 00103 { 00104 XmString str; 00105 char *name = net->Name; 00106 name[0] = ' '; 00107 net->flag = 1; 00108 str = XmStringCreatePCB (name); 00109 XmListReplaceItemsPos (netlist_list, &str, 1, pos); 00110 XmStringFree (str); 00111 } 00112 00113 static void 00114 nbcb_rat_off (LibraryMenuType *net, int pos) 00115 { 00116 XmString str; 00117 char *name = net->Name; 00118 name[0] = '*'; 00119 net->flag = 0; 00120 str = XmStringCreatePCB (name); 00121 XmListReplaceItemsPos (netlist_list, &str, 1, pos); 00122 XmStringFree (str); 00123 } 00124 00125 00126 /* Select on the layout the current net treeview selection 00127 */ 00128 static void 00129 nbcb_select_common (LibraryMenuType *net, int pos, int select_flag) 00130 { 00131 LibraryEntryType *entry; 00132 ConnectionType conn; 00133 int i; 00134 00135 InitConnectionLookup (); 00136 ClearFlagOnAllObjects (true, FOUNDFLAG); 00137 00138 for (i = net->EntryN, entry = net->Entry; i; i--, entry++) 00139 if (SeekPad (entry, &conn, false)) 00140 RatFindHook (conn.type, conn.ptr1, conn.ptr2, conn.ptr2, true, FOUNDFLAG, true); 00141 00142 SelectByFlag (FOUNDFLAG, select_flag); 00143 ClearFlagOnAllObjects (false, FOUNDFLAG); 00144 FreeConnectionLookupMemory (); 00145 IncrementUndoSerialNumber (); 00146 Draw (); 00147 } 00148 00149 static void 00150 nbcb_select (LibraryMenuType *net, int pos) 00151 { 00152 nbcb_select_common (net, pos, 1); 00153 } 00154 00155 static void 00156 nbcb_deselect (LibraryMenuType *net, int pos) 00157 { 00158 nbcb_select_common (net, pos, 0); 00159 } 00160 00161 static void 00162 nbcb_find (LibraryMenuType *net, int pos) 00163 { 00164 char *name = net->Name + 2; 00165 hid_actionl ("netlist", "find", name, NULL); 00166 } 00167 00168 static void 00169 nbcb_std_callback (Widget w, Std_Nbcb_Func v, XmPushButtonCallbackStruct * cbs) 00170 { 00171 int *posl, posc, i; 00172 XmString **items, **selected; 00173 if (XmListGetSelectedPos (netlist_list, &posl, &posc) == False) 00174 return; 00175 if (v == nbcb_find) 00176 hid_actionl ("connection", "reset", NULL); 00177 for (i=0; i<posc; i++) 00178 { 00179 LibraryMenuType *net = & (PCB->NetlistLib.Menu[posl[i] - 1]); 00180 v(net, posl[i]); 00181 } 00182 n = 0; 00183 stdarg (XmNitems, &items); 00184 XtGetValues (netlist_list, args, n); 00185 selected = (XmString **) malloc (posc * sizeof (XmString *)); 00186 for (i=0; i<posc; i++) 00187 selected[i] = items[posl[i]-1]; 00188 00189 n = 0; 00190 stdarg (XmNselectedItems, selected); 00191 XtSetValues (netlist_list, args, n); 00192 } 00193 00194 static void 00195 nbcb_ripup (Widget w, Std_Nbcb_Func v, XmPushButtonCallbackStruct * cbs) 00196 { 00197 nbcb_std_callback (w, nbcb_find, cbs); 00198 00199 VISIBLELINE_LOOP (PCB->Data); 00200 { 00201 if (TEST_FLAG (FOUNDFLAG, line) && !TEST_FLAG (LOCKFLAG, line)) 00202 RemoveObject (LINE_TYPE, layer, line, line); 00203 } 00204 ENDALL_LOOP; 00205 00206 VISIBLEARC_LOOP (PCB->Data); 00207 { 00208 if (TEST_FLAG (FOUNDFLAG, arc) && !TEST_FLAG (LOCKFLAG, arc)) 00209 RemoveObject (ARC_TYPE, layer, arc, arc); 00210 } 00211 ENDALL_LOOP; 00212 00213 if (PCB->ViaOn) 00214 VIA_LOOP (PCB->Data); 00215 { 00216 if (TEST_FLAG (FOUNDFLAG, via) && !TEST_FLAG (LOCKFLAG, via)) 00217 RemoveObject (VIA_TYPE, via, via, via); 00218 } 00219 END_LOOP; 00220 } 00221 00222 static void 00223 netnode_browse (Widget w, XtPointer v, XmListCallbackStruct * cbs) 00224 { 00225 LibraryMenuType *menu = PCB->NetlistLib.Menu + last_pick; 00226 char *name = menu->Entry[cbs->item_position - 1].ListEntry; 00227 char *ename, *pname; 00228 00229 ename = strdup (name); 00230 pname = strchr (ename, '-'); 00231 if (! pname) 00232 { 00233 free (ename); 00234 return; 00235 } 00236 *pname++ = 0; 00237 00238 ELEMENT_LOOP (PCB->Data); 00239 { 00240 char *es = element->Name[NAMEONPCB_INDEX].TextString; 00241 if (es && strcmp (es, ename) == 0) 00242 { 00243 PIN_LOOP (element); 00244 { 00245 if (strcmp (pin->Number, pname) == 0) 00246 { 00247 MoveCrosshairAbsolute (pin->X, pin->Y); 00248 free (ename); 00249 return; 00250 } 00251 } 00252 END_LOOP; 00253 PAD_LOOP (element); 00254 { 00255 if (strcmp (pad->Number, pname) == 0) 00256 { 00257 int x = (pad->Point1.X + pad->Point2.X) / 2; 00258 int y = (pad->Point1.Y + pad->Point2.Y) / 2; 00259 gui->set_crosshair (x, y, HID_SC_PAN_VIEWPORT); 00260 free (ename); 00261 return; 00262 } 00263 } 00264 END_LOOP; 00265 } 00266 } 00267 END_LOOP; 00268 free (ename); 00269 } 00270 00271 #define NLB_FORM ((Widget)(~0)) 00272 static Widget 00273 netlist_button (Widget parent, char *name, char *string, 00274 Widget top, Widget bottom, Widget left, Widget right, 00275 XtCallbackProc callback, void *user_data) 00276 { 00277 Widget rv; 00278 XmString str; 00279 00280 #define NLB_W(w) if (w == NLB_FORM) { stdarg(XmN ## w ## Attachment, XmATTACH_FORM); } \ 00281 else if (w) { stdarg(XmN ## w ## Attachment, XmATTACH_WIDGET); \ 00282 stdarg (XmN ## w ## Widget, w); } 00283 00284 NLB_W (top); 00285 NLB_W (bottom); 00286 NLB_W (left); 00287 NLB_W (right); 00288 str = XmStringCreatePCB (string); 00289 stdarg(XmNlabelString, str); 00290 rv = XmCreatePushButton (parent, name, args, n); 00291 XtManageChild (rv); 00292 if (callback) 00293 XtAddCallback (rv, XmNactivateCallback, callback, (XtPointer)user_data); 00294 XmStringFree(str); 00295 return rv; 00296 } 00297 00298 static int 00299 build_netlist_dialog () 00300 { 00301 Widget b_sel, b_unsel, b_find, b_rat_on, l_ops; 00302 XmString ops_str; 00303 00304 if (!mainwind) 00305 return 1; 00306 if (netlist_dialog) 00307 return 0; 00308 00309 n = 0; 00310 stdarg (XmNresizePolicy, XmRESIZE_GROW); 00311 stdarg (XmNtitle, "Netlists"); 00312 stdarg (XmNautoUnmanage, False); 00313 netlist_dialog = XmCreateFormDialog (mainwind, "netlist", args, n); 00314 00315 n = 0; 00316 b_rat_on = netlist_button (netlist_dialog, "rat_on", "Enable for rats", 00317 0, NLB_FORM, NLB_FORM, 0, 00318 (XtCallbackProc)nbcb_std_callback, (void *)nbcb_rat_on); 00319 00320 n = 0; 00321 netlist_button (netlist_dialog, "rat_off", "Disable for rats", 00322 0, NLB_FORM, b_rat_on, 0, 00323 (XtCallbackProc)nbcb_std_callback, (void *)nbcb_rat_off); 00324 00325 n = 0; 00326 b_sel = netlist_button (netlist_dialog, "select", "Select", 00327 0, b_rat_on, NLB_FORM, 0, 00328 (XtCallbackProc)nbcb_std_callback, (void *)nbcb_select); 00329 00330 n = 0; 00331 b_unsel = netlist_button (netlist_dialog, "deselect", "Deselect", 00332 0, b_rat_on, b_sel, 0, 00333 (XtCallbackProc)nbcb_std_callback, (void *)nbcb_deselect); 00334 00335 n = 0; 00336 b_find = netlist_button (netlist_dialog, "find", "Find", 00337 0, b_rat_on, b_unsel, 0, 00338 (XtCallbackProc)nbcb_std_callback, (void *)nbcb_find); 00339 00340 00341 n = 0; 00342 netlist_button (netlist_dialog, "ripup", "Rip Up", 00343 0, b_rat_on, b_find, 0, 00344 (XtCallbackProc)nbcb_ripup, 0); 00345 00346 n = 0; 00347 stdarg (XmNbottomAttachment, XmATTACH_WIDGET); 00348 stdarg (XmNbottomWidget, b_sel); 00349 stdarg (XmNleftAttachment, XmATTACH_FORM); 00350 ops_str = XmStringCreatePCB ("Operations on selected net names:"); 00351 stdarg (XmNlabelString, ops_str); 00352 l_ops = XmCreateLabel (netlist_dialog, "ops", args, n); 00353 XtManageChild (l_ops); 00354 00355 n = 0; 00356 stdarg (XmNtopAttachment, XmATTACH_FORM); 00357 stdarg (XmNbottomAttachment, XmATTACH_WIDGET); 00358 stdarg (XmNbottomWidget, l_ops); 00359 stdarg (XmNleftAttachment, XmATTACH_FORM); 00360 stdarg (XmNrightAttachment, XmATTACH_POSITION); 00361 stdarg (XmNrightPosition, 50); 00362 stdarg (XmNvisibleItemCount, 10); 00363 stdarg (XmNselectionPolicy, XmEXTENDED_SELECT); 00364 netlist_list = XmCreateScrolledList (netlist_dialog, "nets", args, n); 00365 XtManageChild (netlist_list); 00366 XtAddCallback (netlist_list, XmNdefaultActionCallback, (XtCallbackProc)netlist_select, 0); 00367 XtAddCallback (netlist_list, XmNextendedSelectionCallback, (XtCallbackProc)netlist_extend, 0); 00368 00369 n = 0; 00370 stdarg (XmNtopAttachment, XmATTACH_FORM); 00371 stdarg (XmNbottomAttachment, XmATTACH_WIDGET); 00372 stdarg (XmNbottomWidget, l_ops); 00373 stdarg (XmNrightAttachment, XmATTACH_FORM); 00374 stdarg (XmNleftAttachment, XmATTACH_POSITION); 00375 stdarg (XmNleftPosition, 50); 00376 netnode_list = XmCreateScrolledList (netlist_dialog, "nodes", args, n); 00377 XtManageChild (netnode_list); 00378 XtAddCallback (netnode_list, XmNbrowseSelectionCallback, (XtCallbackProc)netnode_browse, 0); 00379 00380 return 0; 00381 } 00382 00383 static int 00384 LesstifNetlistChanged (int argc, char **argv, Coord x, Coord y) 00385 { 00386 int i; 00387 if (!PCB->NetlistLib.MenuN) 00388 return 0; 00389 if (build_netlist_dialog ()) 00390 return 0; 00391 last_pick = -1; 00392 if (netlist_strings) 00393 free (netlist_strings); 00394 netlist_strings = 00395 (XmString *) malloc (PCB->NetlistLib.MenuN * sizeof (XmString)); 00396 for (i = 0; i < PCB->NetlistLib.MenuN; i++) 00397 netlist_strings[i] = 00398 XmStringCreatePCB (PCB->NetlistLib.Menu[i].Name); 00399 n = 0; 00400 stdarg (XmNitems, netlist_strings); 00401 stdarg (XmNitemCount, PCB->NetlistLib.MenuN); 00402 XtSetValues (netlist_list, args, n); 00403 pick_net (0); 00404 return 0; 00405 } 00406 00407 static const char netlistshow_syntax[] = 00408 "NetlistShow(pinname|netname)"; 00409 00410 static const char netlistshow_help[] = 00411 "Selects the given pinname or netname in the netlist window."; 00412 00413 /* %start-doc actions NetlistShow 00414 00415 %end-doc */ 00416 00417 static int 00418 LesstifNetlistShow (int argc, char **argv, Coord x, Coord y) 00419 { 00420 if (build_netlist_dialog ()) 00421 return 0; 00422 00423 if (argc == 1) 00424 { 00425 LibraryMenuType *net; 00426 00427 net = netnode_to_netname(argv[0]); 00428 if (net) 00429 { 00430 XmString item; 00431 int vis = 0; 00432 00433 /* Select net first, 'True' causes pick_net() to be invoked */ 00434 item = XmStringCreatePCB (net->Name); 00435 XmListSelectItem (netlist_list, item, True); 00436 XmListSetItem (netlist_list, item); 00437 XmStringFree (item); 00438 00439 /* Now the netnode_list has the right contents */ 00440 item = XmStringCreatePCB (argv[0]); 00441 XmListSelectItem (netnode_list, item, False); 00442 00443 /* 00444 * Only force the item to the top if there are enough to scroll. 00445 * A bug (?) in lesstif will cause the window to get ever wider 00446 * if an XmList that doesn't require a scrollbar is forced to 00447 * have one (when the top item is not the first item). 00448 */ 00449 n = 0; 00450 stdarg (XmNvisibleItemCount, &vis); 00451 XtGetValues (netnode_list, args, n); 00452 if (n_netnode_strings > vis) 00453 { 00454 XmListSetItem (netnode_list, item); 00455 } 00456 XmStringFree (item); 00457 } 00458 else 00459 { 00460 /* Try the argument as a netname */ 00461 net = netname_to_netname(argv[0]); 00462 if (net) 00463 { 00464 XmString item; 00465 00466 item = XmStringCreatePCB (net->Name); 00467 XmListSetItem (netlist_list, item); 00468 XmListSelectItem (netlist_list, item, True); 00469 XmStringFree (item); 00470 } 00471 } 00472 } 00473 return 0; 00474 } 00475 00476 void 00477 lesstif_show_netlist () 00478 { 00479 build_netlist_dialog (); 00480 XtManageChild (netlist_dialog); 00481 } 00482 00483 HID_Action lesstif_netlist_action_list[] = { 00484 {"NetlistChanged", 0, LesstifNetlistChanged, 00485 netlistchanged_help, netlistchanged_syntax}, 00486 {"NetlistShow", 0, LesstifNetlistShow, 00487 netlistshow_help, netlistshow_syntax} 00488 }; 00489 00490 REGISTER_ACTIONS (lesstif_netlist_action_list)