pcb 4.1.1
An interactive printed circuit board layout editor.

hid/lesstif/netlist.c

Go to the documentation of this file.
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)