pcb 4.1.1
An interactive printed circuit board layout editor.

styles.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 #include "set.h"
00016 #include "misc.h"
00017 #include "mymem.h"
00018 #include "pcb-printf.h"
00019 
00020 #include "hid.h"
00021 #include "../hidint.h"
00022 #include "lesstif.h"
00023 
00024 #ifdef HAVE_LIBDMALLOC
00025 #include <dmalloc.h>
00026 #endif
00027 
00028 /* There are three places where styles are kept:
00029 
00030    First, the "active" style is in Settings.LineThickness et al.
00031 
00032    Second, there are NUM_STYLES styles in PCB->RouteStyle[].
00033 
00034    Third, there are NUM_STYLES styles in Settings.RouteStyle[]
00035 
00036    Selecting a style copies its values to the active style.  We also
00037    need a way to modify the active style, copy the active style to
00038    PCB->RouteStyle[], and copy PCB->RouteStyle[] to
00039    Settings.RouteStyle[].  Since Lesstif reads the default style from
00040    .Xdefaults, we can ignore Settings.RouteStyle[] in general, as it's
00041    only used to initialize new PCB files.
00042 
00043    So, we need to do PCB->RouteStyle <-> active style.
00044 */
00045 
00046 static Arg args[30];
00047 static int n;
00048 #define stdarg(t,v) XtSetArg(args[n], t, v); n++
00049 
00050 typedef enum
00051 {
00052   SSthick, SSdiam, SShole, SSkeep,
00053   SSNUM
00054 } StyleValues;
00055 
00056 static Widget style_dialog = 0;
00057 static Widget style_values[SSNUM];
00058 static Widget style_pb[NUM_STYLES];
00059 static Widget units_pb[NUM_STYLES];
00060 static int name_hashes[NUM_STYLES];
00061 static Widget value_form, value_labels, value_texts, units_form;
00062 static int local_update = 0;
00063 XmString xms_mm, xms_mil;
00064 
00065 static const Unit *unit = 0;
00066 static XmString ustr;
00067 
00068 static int
00069 hash (char *cp)
00070 {
00071   int h = 0;
00072   while (*cp)
00073     {
00074       h = h * 13 + *(unsigned char *) cp;
00075       h ^= (h >> 16);
00076       cp++;
00077     }
00078   return h;
00079 }
00080 
00081 typedef struct
00082 {
00083   Widget w[NUM_STYLES];
00084 } StyleButtons;
00085 
00086 static StyleButtons *style_button_list = 0;
00087 static int num_style_buttons = 0;
00088 
00089 static char *value_names[] = {
00090   "Thickness", "Diameter", "Hole", "Keepaway"
00091 };
00092 
00093 static int RouteStylesChanged (int argc, char **argv, Coord x, Coord y);
00094 
00095 static void
00096 update_one_value (int i, Coord v)
00097 {
00098   char buf[100];
00099 
00100   pcb_snprintf (buf, sizeof (buf), "%m+%.2mS", unit->allow, v);
00101   XmTextSetString (style_values[i], buf);
00102   n = 0;
00103   stdarg (XmNlabelString, ustr);
00104   XtSetValues (units_pb[i], args, n);
00105 }
00106 
00107 static void
00108 update_values ()
00109 {
00110   local_update = 1;
00111   update_one_value (SSthick, Settings.LineThickness);
00112   update_one_value (SSdiam, Settings.ViaThickness);
00113   update_one_value (SShole, Settings.ViaDrillingHole);
00114   update_one_value (SSkeep, Settings.Keepaway);
00115   local_update = 0;
00116   lesstif_update_status_line ();
00117 }
00118 
00119 void
00120 lesstif_styles_update_values ()
00121 {
00122   if (!style_dialog)
00123     {
00124       lesstif_update_status_line ();
00125       return;
00126     }
00127   unit = Settings.grid_unit;
00128   ustr = XmStringCreateLocalized ((char *)Settings.grid_unit->suffix);
00129   update_values ();
00130 }
00131 
00132 static void
00133 update_style_buttons ()
00134 {
00135   int i = hid_get_flag ("style");
00136   int j, n;
00137 
00138   for (n = 0; n < num_style_buttons; n++)
00139     {
00140       for (j = 0; j < NUM_STYLES; j++)
00141         if (j != i - 1)
00142           XmToggleButtonSetState (style_button_list[n].w[j], 0, 0);
00143         else
00144           XmToggleButtonSetState (style_button_list[n].w[j], 1, 0);
00145     }
00146   if (style_dialog)
00147     {
00148       for (j = 0; j < NUM_STYLES; j++)
00149         if (j != i - 1)
00150           XmToggleButtonSetState (style_pb[j], 0, 0);
00151         else
00152           XmToggleButtonSetState (style_pb[j], 1, 0);
00153     }
00154 }
00155 
00156 static void
00157 style_value_cb (Widget w, int i, void *cbs)
00158 {
00159   Coord n;
00160   char *s;
00161 
00162   if (local_update)
00163     return;
00164   s = XmTextGetString (w);
00165   n = GetValueEx (s, NULL, NULL, NULL, unit->suffix);
00166   switch (i)
00167     {
00168     case SSthick:
00169       Settings.LineThickness = n;
00170       break;
00171     case SSdiam:
00172       Settings.ViaThickness = n;
00173       break;
00174     case SShole:
00175       Settings.ViaDrillingHole = n;
00176       break;
00177     case SSkeep:
00178       Settings.Keepaway = n;
00179       break;
00180     }
00181   update_style_buttons ();
00182 }
00183 
00184 static void
00185 units_cb ()
00186 {
00187   if (unit == get_unit_struct ("mm"))
00188     unit = get_unit_struct ("mil");
00189   else
00190     unit = get_unit_struct ("mm");
00191   ustr = XmStringCreateLocalized ((char *)unit->suffix);
00192   update_values ();
00193 }
00194 
00195 static Widget
00196 style_value (int i)
00197 {
00198   Widget w, l;
00199   n = 0;
00200   stdarg (XmNtopAttachment, XmATTACH_POSITION);
00201   stdarg (XmNtopPosition, i);
00202   stdarg (XmNbottomAttachment, XmATTACH_POSITION);
00203   stdarg (XmNbottomPosition, i + 1);
00204   stdarg (XmNleftAttachment, XmATTACH_FORM);
00205   stdarg (XmNrightAttachment, XmATTACH_FORM);
00206   stdarg (XmNalignment, XmALIGNMENT_END);
00207   l = XmCreateLabel (value_labels, value_names[i], args, n);
00208   XtManageChild (l);
00209 
00210   n = 0;
00211   stdarg (XmNtopAttachment, XmATTACH_POSITION);
00212   stdarg (XmNtopPosition, i);
00213   stdarg (XmNbottomAttachment, XmATTACH_POSITION);
00214   stdarg (XmNbottomPosition, i + 1);
00215   stdarg (XmNleftAttachment, XmATTACH_FORM);
00216   stdarg (XmNrightAttachment, XmATTACH_FORM);
00217   stdarg (XmNcolumns, 8);
00218   w = XmCreateTextField (value_texts, value_names[i], args, n);
00219   XtAddCallback (w, XmNvalueChangedCallback,
00220                  (XtCallbackProc) style_value_cb, (XtPointer) (size_t) i);
00221   XtManageChild (w);
00222 
00223   n = 0;
00224   stdarg (XmNtopAttachment, XmATTACH_POSITION);
00225   stdarg (XmNtopPosition, i);
00226   stdarg (XmNbottomAttachment, XmATTACH_POSITION);
00227   stdarg (XmNbottomPosition, i + 1);
00228   stdarg (XmNleftAttachment, XmATTACH_FORM);
00229   stdarg (XmNrightAttachment, XmATTACH_FORM);
00230   stdarg (XmNlabelString, ustr);
00231   units_pb[i] = XmCreatePushButton (units_form, value_names[i], args, n);
00232   XtAddCallback (units_pb[i], XmNactivateCallback,
00233                  (XtCallbackProc) units_cb, (XtPointer) (size_t) i);
00234   XtManageChild (units_pb[i]);
00235 
00236   return w;
00237 }
00238 
00239 static void
00240 style_name_cb (Widget w, int i, XmToggleButtonCallbackStruct * cbs)
00241 {
00242   char *newname = lesstif_prompt_for ("New name", PCB->RouteStyle[i].Name);
00243   free (PCB->RouteStyle[i].Name);
00244   PCB->RouteStyle[i].Name = newname;
00245   RouteStylesChanged (0, 0, 0, 0);
00246 }
00247 
00248 static void
00249 style_set_cb (Widget w, int i, XmToggleButtonCallbackStruct * cbs)
00250 {
00251   PCB->RouteStyle[i].Thick = Settings.LineThickness;
00252   PCB->RouteStyle[i].Diameter = Settings.ViaThickness;
00253   PCB->RouteStyle[i].Hole = Settings.ViaDrillingHole;
00254   PCB->RouteStyle[i].Keepaway = Settings.Keepaway;
00255   update_style_buttons ();
00256 }
00257 
00258 static void
00259 style_selected (Widget w, int i, XmToggleButtonCallbackStruct * cbs)
00260 {
00261   RouteStyleType *style;
00262   int j, n;
00263   if (cbs && cbs->set == 0)
00264     {
00265       XmToggleButtonSetState (w, 1, 0);
00266       return;
00267     }
00268   style = PCB->RouteStyle + i;
00269   SetLineSize (style->Thick);
00270   SetViaSize (style->Diameter, true);
00271   SetViaDrillingHole (style->Hole, true);
00272   SetKeepawayWidth (style->Keepaway);
00273   if (style_dialog)
00274     {
00275       for (j = 0; j < NUM_STYLES; j++)
00276         if (j != i)
00277           XmToggleButtonSetState (style_pb[j], 0, 0);
00278         else
00279           XmToggleButtonSetState (style_pb[j], 1, 0);
00280       update_values ();
00281     }
00282   else
00283     lesstif_update_status_line ();
00284   for (n = 0; n < num_style_buttons; n++)
00285     {
00286       for (j = 0; j < NUM_STYLES; j++)
00287         if (j != i)
00288           XmToggleButtonSetState (style_button_list[n].w[j], 0, 0);
00289         else
00290           XmToggleButtonSetState (style_button_list[n].w[j], 1, 0);
00291     }
00292 }
00293 
00294 static Widget
00295 style_button (int i)
00296 {
00297   Widget pb, set;
00298 
00299   n = 0;
00300   stdarg (XmNtopAttachment, XmATTACH_WIDGET);
00301   stdarg (XmNtopWidget, i ? style_pb[i - 1] : value_form);
00302   stdarg (XmNleftAttachment, XmATTACH_FORM);
00303   stdarg (XmNlabelString, XmStringCreatePCB ("Name"));
00304   set = XmCreatePushButton (style_dialog, "style", args, n);
00305   XtManageChild (set);
00306   XtAddCallback (set, XmNactivateCallback,
00307                  (XtCallbackProc) style_name_cb, (XtPointer) (size_t) i);
00308 
00309   n = 0;
00310   stdarg (XmNtopAttachment, XmATTACH_WIDGET);
00311   stdarg (XmNtopWidget, i ? style_pb[i - 1] : value_form);
00312   stdarg (XmNleftAttachment, XmATTACH_WIDGET);
00313   stdarg (XmNleftWidget, set);
00314   stdarg (XmNlabelString, XmStringCreatePCB ("Set"));
00315   set = XmCreatePushButton (style_dialog, "style", args, n);
00316   XtManageChild (set);
00317   XtAddCallback (set, XmNactivateCallback,
00318                  (XtCallbackProc) style_set_cb, (XtPointer) (size_t) i);
00319 
00320   n = 0;
00321   stdarg (XmNtopAttachment, XmATTACH_WIDGET);
00322   stdarg (XmNtopWidget, i ? style_pb[i - 1] : value_form);
00323   stdarg (XmNrightAttachment, XmATTACH_FORM);
00324   stdarg (XmNleftAttachment, XmATTACH_WIDGET);
00325   stdarg (XmNleftWidget, set);
00326   stdarg (XmNlabelString, XmStringCreatePCB (PCB->RouteStyle[i].Name));
00327   stdarg (XmNindicatorType, XmONE_OF_MANY);
00328   stdarg (XmNalignment, XmALIGNMENT_BEGINNING);
00329   pb = XmCreateToggleButton (style_dialog, "style", args, n);
00330   XtManageChild (pb);
00331   XtAddCallback (pb, XmNvalueChangedCallback,
00332                  (XtCallbackProc) style_selected, (XtPointer) (size_t) i);
00333   return pb;
00334 }
00335 
00336 static const char adjuststyle_syntax[] =
00337 "AdjustStyle()";
00338 
00339 static const char adjuststyle_help[] =
00340 "Displays the route style adjustment window.";
00341 
00342 /* %start-doc actions AdjustStyle
00343 
00344 %end-doc */
00345 
00346 static int
00347 AdjustStyle (int argc, char **argv, Coord x, Coord y)
00348 {
00349   if (!mainwind)
00350     return 1;
00351   if (style_dialog == 0)
00352     {
00353       int i;
00354 
00355       unit = Settings.grid_unit;
00356       ustr = XmStringCreateLocalized ((char *)unit->suffix);
00357 
00358       n = 0;
00359       stdarg (XmNautoUnmanage, False);
00360       stdarg (XmNtitle, "Route Styles");
00361       style_dialog = XmCreateFormDialog (mainwind, "style", args, n);
00362 
00363       n = 0;
00364       stdarg (XmNtopAttachment, XmATTACH_FORM);
00365       stdarg (XmNleftAttachment, XmATTACH_FORM);
00366       stdarg (XmNrightAttachment, XmATTACH_FORM);
00367       value_form = XmCreateForm (style_dialog, "values", args, n);
00368       XtManageChild (value_form);
00369 
00370       n = 0;
00371       stdarg (XmNtopAttachment, XmATTACH_FORM);
00372       stdarg (XmNrightAttachment, XmATTACH_FORM);
00373       stdarg (XmNbottomAttachment, XmATTACH_FORM);
00374       stdarg (XmNfractionBase, 4);
00375       stdarg (XmNresizePolicy, XmRESIZE_GROW);
00376       units_form = XmCreateForm (value_form, "units", args, n);
00377       XtManageChild (units_form);
00378 
00379       n = 0;
00380       stdarg (XmNtopAttachment, XmATTACH_FORM);
00381       stdarg (XmNbottomAttachment, XmATTACH_FORM);
00382       stdarg (XmNleftAttachment, XmATTACH_FORM);
00383       stdarg (XmNfractionBase, 4);
00384       value_labels = XmCreateForm (value_form, "values", args, n);
00385       XtManageChild (value_labels);
00386 
00387       n = 0;
00388       stdarg (XmNtopAttachment, XmATTACH_FORM);
00389       stdarg (XmNbottomAttachment, XmATTACH_FORM);
00390       stdarg (XmNrightAttachment, XmATTACH_WIDGET);
00391       stdarg (XmNrightWidget, units_form);
00392       stdarg (XmNleftAttachment, XmATTACH_WIDGET);
00393       stdarg (XmNleftWidget, value_labels);
00394       stdarg (XmNfractionBase, 4);
00395       value_texts = XmCreateForm (value_form, "values", args, n);
00396       XtManageChild (value_texts);
00397 
00398       for (i = 0; i < SSNUM; i++)
00399         {
00400           style_values[i] = style_value (i);
00401           name_hashes[i] = hash (PCB->RouteStyle[i].Name);
00402         }
00403       for (i = 0; i < NUM_STYLES; i++)
00404         style_pb[i] = style_button (i);
00405       update_values ();
00406       update_style_buttons ();
00407     }
00408   XtManageChild (style_dialog);
00409   return 0;
00410 }
00411 
00412 static int
00413 RouteStylesChanged (int argc, char **argv, Coord x, Coord y)
00414 {
00415   int i, j, h;
00416   if (!PCB || !PCB->RouteStyle[0].Name)
00417     return 0;
00418   update_style_buttons ();
00419   if (!style_dialog)
00420     return 0;
00421   for (j = 0; j < NUM_STYLES; j++)
00422     {
00423       h = hash (PCB->RouteStyle[j].Name);
00424       if (name_hashes[j] == h)
00425         continue;
00426       name_hashes[j] = h;
00427       n = 0;
00428       stdarg (XmNlabelString,
00429               XmStringCreatePCB (PCB->RouteStyle[j].Name));
00430       if (style_dialog)
00431         XtSetValues (style_pb[j], args, n);
00432       for (i = 0; i < num_style_buttons; i++)
00433         XtSetValues (style_button_list[i].w[j], args, n);
00434     }
00435   update_values ();
00436   return 0;
00437 }
00438 
00439 void
00440 lesstif_insert_style_buttons (Widget menu)
00441 {
00442   StyleButtons *sb;
00443   int s, i;
00444 
00445   num_style_buttons++;
00446   s = num_style_buttons * sizeof (StyleButtons);
00447   style_button_list = (StyleButtons *) realloc (style_button_list, s);
00448   sb = style_button_list + num_style_buttons - 1;
00449 
00450   for (i = 0; i < NUM_STYLES; i++)
00451     {
00452       Widget btn;
00453       n = 0;
00454       stdarg (XmNindicatorType, XmONE_OF_MANY);
00455       stdarg (XmNlabelString,
00456               XmStringCreatePCB (PCB->RouteStyle[i].Name));
00457       btn = XmCreateToggleButton (menu, "style", args, n);
00458       XtManageChild (btn);
00459       XtAddCallback (btn, XmNvalueChangedCallback,
00460                      (XtCallbackProc) style_selected, (XtPointer) (size_t) i);
00461       sb->w[i] = btn;
00462     }
00463   update_style_buttons ();
00464 }
00465 
00466 HID_Action lesstif_styles_action_list[] = {
00467   {"AdjustStyle", 0, AdjustStyle,
00468    adjuststyle_help, adjuststyle_syntax},
00469   {"RouteStylesChanged", 0, RouteStylesChanged,
00470    routestyleschanged_help, routestyleschanged_syntax}
00471 };
00472 
00473 REGISTER_ACTIONS (lesstif_styles_action_list)