Introduce POLYGONHOLE_MODE for creating holes in polygons
[geda-pcb/gde.git] / src / vendor.c
blob39359cc893ae74e211fb04b0b8e28cd99c7878e9
1 /* $Id$ */
3 /*
4 * COPYRIGHT
6 * PCB, interactive printed circuit board design
7 * Copyright (C) 2004, 2007 Dan McMahill
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
29 #include <ctype.h>
30 #include <math.h>
31 #include <stdio.h>
33 #ifdef HAVE_STDLIB_H
34 #include <stdlib.h>
35 #endif
37 #ifdef HAVE_STRING_H
38 #include <string.h>
39 #endif
41 #ifdef HAVE_SYS_TYPES_H
42 #include <sys/types.h>
43 #endif
45 #ifdef HAVE_REGEX_H
46 #include <regex.h>
47 #else
48 #ifdef HAVE_UNISTD_H
49 #include <unistd.h>
50 #endif
51 #endif
53 #include "change.h"
54 #include "data.h"
55 #include "draw.h"
56 #include "error.h"
57 #include "global.h"
58 #include "resource.h"
59 #include "set.h"
60 #include "undo.h"
61 #include "vendor.h"
63 #ifdef HAVE_LIBDMALLOC
64 #include <dmalloc.h>
65 #endif
67 RCSID ("$Id$");
69 static void add_to_drills (char *);
70 static void apply_vendor_map (void);
71 static void process_skips (Resource *);
72 static bool rematch (const char *, const char *);
74 /* list of vendor drills and a count of them */
75 static int *vendor_drills = NULL;
76 static int n_vendor_drills = 0;
78 static int cached_drill = -1;
79 static int cached_map = -1;
81 /* lists of elements to ignore */
82 static char **ignore_refdes = NULL;
83 static int n_refdes = 0;
84 static char **ignore_value = NULL;
85 static int n_value = 0;
86 static char **ignore_descr = NULL;
87 static int n_descr = 0;
89 /* vendor name */
90 static char *vendor_name = NULL;
92 /* resource file to PCB units scale factor */
93 static double sf;
96 /* enable/disable mapping */
97 static bool vendorMapEnable = false;
99 /* type of drill mapping */
100 #define CLOSEST 1
101 #define ROUND_UP 0
102 static int rounding_method = ROUND_UP;
104 #define FREE(x) if((x) != NULL) { free (x) ; (x) = NULL; }
106 /* ************************************************************ */
108 static const char apply_vendor_syntax[] = "ApplyVendor()";
110 static const char apply_vendor_help[] =
111 "Applies the currently loaded vendor drill table to the current design.";
113 /* %start-doc actions ApplyVendor
114 @cindex vendor map
115 @cindex vendor drill table
116 @findex ApplyVendor()
118 This will modify all of your drill holes to match the list of allowed
119 sizes for your vendor.
120 %end-doc */
123 ActionApplyVendor (int argc, char **argv, int x, int y)
125 hid_action ("Busy");
126 apply_vendor_map ();
127 return 0;
130 /* ************************************************************ */
132 static const char toggle_vendor_syntax[] = "ToggleVendor()";
134 static const char toggle_vendor_help[] =
135 "Toggles the state of automatic drill size mapping.";
137 /* %start-doc actions ToggleVendor
139 @cindex vendor map
140 @cindex vendor drill table
141 @findex ToggleVendor()
143 When drill mapping is enabled, new instances of pins and vias will
144 have their drill holes mapped to one of the allowed drill sizes
145 specified in the currently loaded vendor drill table. To enable drill
146 mapping, a vendor resource file containing a drill table must be
147 loaded first.
149 %end-doc */
152 ActionToggleVendor (int argc, char **argv, int x, int y)
154 if (vendorMapEnable)
155 vendorMapEnable = false;
156 else
157 vendorMapEnable = true;
158 return 0;
161 /* ************************************************************ */
163 static const char enable_vendor_syntax[] = "EnableVendor()";
165 static const char enable_vendor_help[] =
166 "Enables automatic drill size mapping.";
168 /* %start-doc actions EnableVendor
170 @cindex vendor map
171 @cindex vendor drill table
172 @findex EnableVendor()
174 When drill mapping is enabled, new instances of pins and vias will
175 have their drill holes mapped to one of the allowed drill sizes
176 specified in the currently loaded vendor drill table. To enable drill
177 mapping, a vendor resource file containing a drill table must be
178 loaded first.
180 %end-doc */
183 ActionEnableVendor (int argc, char **argv, int x, int y)
185 vendorMapEnable = true;
186 return 0;
189 /* ************************************************************ */
191 static const char disable_vendor_syntax[] = "DisableVendor()";
193 static const char disable_vendor_help[] =
194 "Disables automatic drill size mapping.";
196 /* %start-doc actions DisableVendor
198 @cindex vendor map
199 @cindex vendor drill table
200 @findex DisableVendor()
202 When drill mapping is enabled, new instances of pins and vias will
203 have their drill holes mapped to one of the allowed drill sizes
204 specified in the currently loaded vendor drill table.
206 %end-doc */
209 ActionDisableVendor (int argc, char **argv, int x, int y)
211 vendorMapEnable = false;
212 return 0;
215 /* ************************************************************ */
217 static const char unload_vendor_syntax[] = "UnloadVendor()";
219 static const char unload_vendor_help[] =
220 "Unloads the current vendor drill mapping table.";
222 /* %start-doc actions UnloadVendor
224 @cindex vendor map
225 @cindex vendor drill table
226 @findex UnloadVendor()
228 %end-doc */
231 ActionUnloadVendor (int argc, char **argv, int x, int y)
233 cached_drill = -1;
235 /* Unload any vendor table we may have had */
236 n_vendor_drills = 0;
237 n_refdes = 0;
238 n_value = 0;
239 n_descr = 0;
240 FREE (vendor_drills);
241 FREE (ignore_refdes);
242 FREE (ignore_value);
243 FREE (ignore_descr);
244 return 0;
247 /* ************************************************************ */
249 static const char load_vendor_syntax[] = "LoadVendorFrom(filename)";
251 static const char load_vendor_help[] =
252 "Loads the specified vendor resource file.";
254 /* %start-doc actions LoadVendorFrom
256 @cindex vendor map
257 @cindex vendor drill table
258 @findex LoadVendorFrom()
260 @table @var
261 @item filename
262 Name of the vendor resource file. If not specified, the user will
263 be prompted to enter one.
264 @end table
266 %end-doc */
269 ActionLoadVendorFrom (int argc, char **argv, int x, int y)
271 int i;
272 char *fname = NULL, *name = NULL;
273 static char *default_file = NULL;
274 char *sval;
275 Resource *res, *drcres, *drlres;
276 int type;
278 cached_drill = -1;
280 fname = argc ? argv[0] : 0;
282 if (!fname || !*fname)
284 fname = gui->fileselect (_("Load Vendor Resource File..."),
285 _("Picks a vendor resource file to load.\n"
286 "This file can contain drc settings for a\n"
287 "particular vendor as well as a list of\n"
288 "predefined drills which are allowed."),
289 default_file, ".res", "vendor",
290 HID_FILESELECT_READ);
291 if (fname == NULL)
292 AFAIL (load_vendor);
294 if (default_file != NULL)
296 free (default_file);
297 default_file = NULL;
300 if (fname && *fname)
301 default_file = strdup (fname);
304 /* Unload any vendor table we may have had */
305 n_vendor_drills = 0;
306 n_refdes = 0;
307 n_value = 0;
308 n_descr = 0;
309 FREE (vendor_drills);
310 FREE (ignore_refdes);
311 FREE (ignore_value);
312 FREE (ignore_descr);
315 /* load the resource file */
316 res = resource_parse (fname, NULL);
317 if (res == NULL)
319 Message (_("Could not load vendor resource file \"%s\"\n"), fname);
320 return 1;
323 /* figure out the vendor name, if specified */
324 vendor_name = UNKNOWN (resource_value (res, "vendor"));
326 /* figure out the units, if specified */
327 sval = resource_value (res, "units");
328 if (sval == NULL)
330 sf = 100;
332 else if ((NSTRCMP (sval, "mil") == 0) || (NSTRCMP (sval, "mils") == 0))
334 sf = 100;
336 else if ((NSTRCMP (sval, "inch") == 0) || (NSTRCMP (sval, "inches") == 0))
338 sf = 100000;
340 else if (NSTRCMP (sval, "mm") == 0)
343 * divide by .0254 to convert mm to mils. Then multiply by 100
344 * for PCB units
346 sf = (100.0 / 0.0254);
348 else
350 Message ("\"%s\" is not a supported units. Defaulting to inch\n",
351 sval);
352 sf = 100000;
356 /* default to ROUND_UP */
357 rounding_method = ROUND_UP;
359 /* extract the drillmap resource */
360 drlres = resource_subres (res, "drillmap");
361 if (drlres == NULL)
363 Message (_("No drillmap resource found\n"));
365 else
367 sval = resource_value (drlres, "round");
368 if (sval != NULL)
370 if (NSTRCMP (sval, "up") == 0)
372 rounding_method = ROUND_UP;
374 else if (NSTRCMP (sval, "nearest") == 0)
376 rounding_method = CLOSEST;
378 else
380 Message (_
381 ("\"%s\" is not a valid rounding type. Defaulting to up\n"),
382 sval);
383 rounding_method = ROUND_UP;
387 process_skips (resource_subres (drlres, "skips"));
389 for (i = 0; i < drlres->c; i++)
391 type = resource_type (drlres->v[i]);
392 switch (type)
394 case 10:
395 /* just a number */
396 add_to_drills (drlres->v[i].value);
397 break;
399 default:
400 break;
405 /* Extract the DRC resource */
406 drcres = resource_subres (res, "drc");
408 sval = resource_value (drcres, "copper_space");
409 if (sval != NULL)
411 PCB->Bloat = floor (sf * atof (sval) + 0.5);
412 Message (_("Set DRC minimum copper spacing to %.2f mils\n"),
413 0.01 * PCB->Bloat);
416 sval = resource_value (drcres, "copper_overlap");
417 if (sval != NULL)
419 PCB->Shrink = floor (sf * atof (sval) + 0.5);
420 Message (_("Set DRC minimum copper overlap to %.2f mils\n"),
421 0.01 * PCB->Shrink);
424 sval = resource_value (drcres, "copper_width");
425 if (sval != NULL)
427 PCB->minWid = floor (sf * atof (sval) + 0.5);
428 Message (_("Set DRC minimum copper spacing to %.2f mils\n"),
429 0.01 * PCB->minWid);
432 sval = resource_value (drcres, "silk_width");
433 if (sval != NULL)
435 PCB->minSlk = floor (sf * atof (sval) + 0.5);
436 Message (_("Set DRC minimum silk width to %.2f mils\n"),
437 0.01 * PCB->minSlk);
440 sval = resource_value (drcres, "min_drill");
441 if (sval != NULL)
443 PCB->minDrill = floor (sf * atof (sval) + 0.5);
444 Message (_("Set DRC minimum drill diameter to %.2f mils\n"),
445 0.01 * PCB->minDrill);
448 sval = resource_value (drcres, "min_ring");
449 if (sval != NULL)
451 PCB->minRing = floor (sf * atof (sval) + 0.5);
452 Message (_("Set DRC minimum annular ring to %.2f mils\n"),
453 0.01 * PCB->minRing);
456 Message (_("Loaded %d vendor drills from %s\n"), n_vendor_drills, fname);
457 Message (_("Loaded %d RefDes skips, %d Value skips, %d Descr skips\n"),
458 n_refdes, n_value, n_descr);
460 vendorMapEnable = true;
461 apply_vendor_map ();
462 free (name);
463 return 0;
466 static void
467 apply_vendor_map (void)
469 int i;
470 int changed, tot;
471 bool state;
473 state = vendorMapEnable;
475 /* enable mapping */
476 vendorMapEnable = true;
478 /* reset our counts */
479 changed = 0;
480 tot = 0;
482 /* If we have loaded vendor drills, then apply them to the design */
483 if (n_vendor_drills > 0)
486 /* first all the vias */
487 VIA_LOOP (PCB->Data);
489 tot++;
490 if (via->DrillingHole != vendorDrillMap (via->DrillingHole))
492 /* only change unlocked vias */
493 if (!TEST_FLAG (LOCKFLAG, via))
495 if (ChangeObject2ndSize (VIA_TYPE, via, NULL, NULL,
496 vendorDrillMap (via->DrillingHole),
497 true, false))
498 changed++;
499 else
501 Message (_
502 ("Via at %.2f, %.2f not changed. Possible reasons:\n"
503 "\t- pad size too small\n"
504 "\t- new size would be too large or too small\n"),
505 0.01 * via->X, 0.01 * via->Y);
508 else
510 Message (_("Locked via at %.2f, %.2f not changed.\n"),
511 0.01 * via->X, 0.01 * via->Y);
515 END_LOOP;
517 /* and now the pins */
518 ELEMENT_LOOP (PCB->Data);
521 * first figure out if this element should be skipped for some
522 * reason
524 if (vendorIsElementMappable (element))
526 /* the element is ok to modify, so iterate over its pins */
527 PIN_LOOP (element);
529 tot++;
530 if (pin->DrillingHole != vendorDrillMap (pin->DrillingHole))
532 if (!TEST_FLAG (LOCKFLAG, pin))
534 if (ChangeObject2ndSize (PIN_TYPE, element, pin, NULL,
535 vendorDrillMap (pin->
536 DrillingHole),
537 true, false))
538 changed++;
539 else
541 Message (_
542 ("Pin %s (%s) at %.2f, %.2f (element %s, %s, %s) not changed.\n"
543 "\tPossible reasons:\n"
544 "\t- pad size too small\n"
545 "\t- new size would be too large or too small\n"),
546 UNKNOWN (pin->Number), UNKNOWN (pin->Name),
547 0.01 * pin->X, 0.01 * pin->Y,
548 UNKNOWN (NAMEONPCB_NAME (element)),
549 UNKNOWN (VALUE_NAME (element)),
550 UNKNOWN (DESCRIPTION_NAME (element)));
553 else
555 Message (_
556 ("Locked pin at %-6.2f, %-6.2f not changed.\n"),
557 0.01 * pin->X, 0.01 * pin->Y);
561 END_LOOP;
564 END_LOOP;
566 Message (_("Updated %d drill sizes out of %d total\n"), changed, tot);
568 /* Update the current Via */
569 if (Settings.ViaDrillingHole !=
570 vendorDrillMap (Settings.ViaDrillingHole))
572 changed++;
573 Settings.ViaDrillingHole =
574 vendorDrillMap (Settings.ViaDrillingHole);
575 Message (_("Adjusted active via hole size to be %6.2f mils\n"),
576 0.01 * Settings.ViaDrillingHole);
579 /* and update the vias for the various routing styles */
580 for (i = 0; i < NUM_STYLES; i++)
582 if (PCB->RouteStyle[i].Hole !=
583 vendorDrillMap (PCB->RouteStyle[i].Hole))
585 changed++;
586 PCB->RouteStyle[i].Hole =
587 vendorDrillMap (PCB->RouteStyle[i].Hole);
588 Message (_
589 ("Adjusted %s routing style via hole size to be %6.2f mils\n"),
590 PCB->RouteStyle[i].Name,
591 0.01 * PCB->RouteStyle[i].Hole);
592 if (PCB->RouteStyle[i].Diameter <
593 PCB->RouteStyle[i].Hole + MIN_PINORVIACOPPER)
595 PCB->RouteStyle[i].Diameter =
596 PCB->RouteStyle[i].Hole + MIN_PINORVIACOPPER;
597 Message (_
598 ("Increased %s routing style via diameter to %6.2f mils\n"),
599 PCB->RouteStyle[i].Name,
600 0.01 * PCB->RouteStyle[i].Diameter);
606 * if we've changed anything, indicate that we need to save the
607 * file, redraw things, and make sure we can undo.
609 if (changed)
611 SetChangedFlag (true);
612 ClearAndRedrawOutput ();
613 IncrementUndoSerialNumber ();
617 /* restore mapping on/off */
618 vendorMapEnable = state;
621 /* for a given drill size, find the closest vendor drill size */
623 vendorDrillMap (int in)
625 int i, min, max;
627 if (in == cached_drill)
628 return cached_map;
629 cached_drill = in;
631 /* skip the mapping if we don't have a vendor drill table */
632 if ((n_vendor_drills == 0) || (vendor_drills == NULL)
633 || (vendorMapEnable == false))
635 cached_map = in;
636 return in;
639 /* are we smaller than the smallest drill? */
640 if (in <= vendor_drills[0])
642 cached_map = vendor_drills[0];
643 return vendor_drills[0];
646 /* are we larger than the largest drill? */
647 if (in > vendor_drills[n_vendor_drills - 1])
649 Message (_("Vendor drill list does not contain a drill >= %6.2f mil\n"
650 "Using %6.2f mil instead.\n"),
651 0.01 * in, 0.01 * vendor_drills[n_vendor_drills - 1]);
652 cached_map = vendor_drills[n_vendor_drills - 1];
653 return vendor_drills[n_vendor_drills - 1];
656 /* figure out which 2 drills are closest in size */
657 min = 0;
658 max = n_vendor_drills - 1;
659 while (max - min > 1)
661 i = (max+min) / 2;
662 if (in > vendor_drills[i])
663 min = i;
664 else
665 max = i;
667 i = max;
669 /* now round per the rounding mode */
670 if (rounding_method == CLOSEST)
672 /* find the closest drill size */
673 if ((in - vendor_drills[i - 1]) > (vendor_drills[i] - in))
675 cached_map = vendor_drills[i];
676 return vendor_drills[i];
678 else
680 cached_map = vendor_drills[i - 1];
681 return vendor_drills[i - 1];
684 else
686 /* always round up */
687 cached_map = vendor_drills[i];
688 return vendor_drills[i];
693 /* add a drill size to the vendor drill list */
694 static void
695 add_to_drills (char *sval)
697 double tmpd;
698 int val;
699 int k, j;
701 /* increment the count and make sure we have memory */
702 n_vendor_drills++;
703 if ((vendor_drills = realloc (vendor_drills,
704 n_vendor_drills * sizeof (int))) == NULL)
706 fprintf (stderr, "realloc() failed to allocate %ld bytes\n",
707 (unsigned long) n_vendor_drills * sizeof (int));
708 return;
711 /* string to a value with the units scale factor in place */
712 tmpd = atof (sval);
713 val = floor (sf * tmpd + 0.5);
716 * We keep the array of vendor drills sorted to make it easier to
717 * do the rounding later. The algorithm used here is not so efficient,
718 * but we're not dealing with much in the way of data.
721 /* figure out where to insert the value to keep the array sorted. */
722 k = 0;
723 while ((k < n_vendor_drills - 1) && (vendor_drills[k] < val))
724 k++;
726 if (k == n_vendor_drills - 1)
728 vendor_drills[n_vendor_drills - 1] = val;
730 else
732 /* move up the existing drills to make room */
733 for (j = n_vendor_drills - 1; j > k; j--)
735 vendor_drills[j] = vendor_drills[j - 1];
738 vendor_drills[k] = val;
742 /* deal with the "skip" subresource */
743 static void
744 process_skips (Resource * res)
746 int type;
747 int i, k;
748 char *sval;
749 int *cnt;
750 char ***lst = NULL;
752 if (res == NULL)
753 return;
755 for (i = 0; i < res->c; i++)
757 type = resource_type (res->v[i]);
758 switch (type)
760 case 1:
762 * an unnamed sub resource. This is something like
763 * {refdes "J3"}
765 sval = res->v[i].subres->v[0].value;
766 if (sval == NULL)
768 Message ("Error: null skip value\n");
770 else
772 if (NSTRCMP (sval, "refdes") == 0)
774 cnt = &n_refdes;
775 lst = &ignore_refdes;
777 else if (NSTRCMP (sval, "value") == 0)
779 cnt = &n_value;
780 lst = &ignore_value;
782 else if (NSTRCMP (sval, "descr") == 0)
784 cnt = &n_descr;
785 lst = &ignore_descr;
787 else
789 cnt = NULL;
792 /* add the entry to the appropriate list */
793 if (cnt != NULL)
795 for (k = 1; k < res->v[i].subres->c; k++)
797 sval = res->v[i].subres->v[k].value;
798 (*cnt)++;
799 if ((*lst =
800 (char **) realloc (*lst,
801 (*cnt) * sizeof (char *))) ==
802 NULL)
804 fprintf (stderr, "realloc() failed\n");
805 exit (-1);
807 (*lst)[*cnt - 1] = strdup (sval);
811 break;
813 default:
814 Message (_("Ignored resource type = %d in skips= section\n"), type);
820 bool
821 vendorIsElementMappable (ElementTypePtr element)
823 int i;
824 int noskip;
826 if (vendorMapEnable == false)
827 return false;
829 noskip = 1;
830 for (i = 0; i < n_refdes; i++)
832 if ((NSTRCMP (UNKNOWN (NAMEONPCB_NAME (element)), ignore_refdes[i]) ==
834 || rematch (ignore_refdes[i], UNKNOWN (NAMEONPCB_NAME (element))))
836 Message (_
837 ("Vendor mapping skipped because refdes = %s matches %s\n"),
838 UNKNOWN (NAMEONPCB_NAME (element)), ignore_refdes[i]);
839 noskip = 0;
842 if (noskip)
843 for (i = 0; i < n_value; i++)
845 if ((NSTRCMP (UNKNOWN (VALUE_NAME (element)), ignore_value[i]) == 0)
846 || rematch (ignore_value[i], UNKNOWN (VALUE_NAME (element))))
848 Message (_
849 ("Vendor mapping skipped because value = %s matches %s\n"),
850 UNKNOWN (VALUE_NAME (element)), ignore_value[i]);
851 noskip = 0;
855 if (noskip)
856 for (i = 0; i < n_descr; i++)
858 if ((NSTRCMP (UNKNOWN (DESCRIPTION_NAME (element)), ignore_descr[i])
859 == 0)
860 || rematch (ignore_descr[i],
861 UNKNOWN (DESCRIPTION_NAME (element))))
863 Message (_
864 ("Vendor mapping skipped because descr = %s matches %s\n"),
865 UNKNOWN (DESCRIPTION_NAME (element)), ignore_descr[i]);
866 noskip = 0;
870 if (noskip && TEST_FLAG (LOCKFLAG, element))
872 Message (_("Vendor mapping skipped because element %s is locked\n"),
873 UNKNOWN (NAMEONPCB_NAME (element)));
874 noskip = 0;
877 if (noskip)
878 return true;
879 else
880 return false;
883 static bool
884 rematch (const char *re, const char *s)
887 * If this system has regular expression capability, then
888 * add support for regular expressions in the skip lists.
891 #if defined(HAVE_REGCOMP)
893 int result;
894 regmatch_t match;
895 regex_t compiled;
897 /* compile the regular expression */
898 result = regcomp (&compiled, re, REG_EXTENDED | REG_ICASE | REG_NOSUB);
899 if (result)
901 char errorstring[128];
903 regerror (result, &compiled, errorstring, sizeof (errorstring));
904 Message ("regexp error: %s\n", errorstring);
905 regfree (&compiled);
906 return (false);
909 result = regexec (&compiled, s, 1, &match, 0);
910 regfree (&compiled);
912 if (result == 0)
913 return (true);
914 else
915 return (false);
917 #elif defined(HAVE_RE_COMP)
918 int m;
919 char *rslt;
921 /* compile the regular expression */
922 if ((rslt = re_comp (re)) != NULL)
924 Message ("re_comp error: %s\n", rslt);
925 return (false);
928 m = re_exec (s);
930 switch m
932 case 1:
933 return (true);
934 break;
936 case 0:
937 return (false);
938 break;
940 default:
941 Message ("re_exec error\n");
942 break;
945 #else
946 return (false);
947 #endif
951 HID_Action vendor_action_list[] = {
952 {"ApplyVendor", 0, ActionApplyVendor,
953 apply_vendor_help, apply_vendor_syntax}
955 {"ToggleVendor", 0, ActionToggleVendor,
956 toggle_vendor_help, toggle_vendor_syntax}
958 {"EnableVendor", 0, ActionEnableVendor,
959 enable_vendor_help, enable_vendor_syntax}
961 {"DisableVendor", 0, ActionDisableVendor,
962 disable_vendor_help, disable_vendor_syntax}
964 {"UnloadVendor", 0, ActionUnloadVendor,
965 unload_vendor_help, unload_vendor_syntax}
967 {"LoadVendorFrom", 0, ActionLoadVendorFrom,
968 load_vendor_help, load_vendor_syntax}
971 REGISTER_ACTIONS (vendor_action_list)
972 static int vendor_get_enabled (int unused)
974 return vendorMapEnable;
977 HID_Flag vendor_flag_list[] = {
978 {"VendorMapOn", vendor_get_enabled, 0}
981 REGISTER_FLAGS (vendor_flag_list)