Fix lockup when a scroll event is received outside the drawing area
[geda-pcb/pcjc2.git] / src / vendor.c
blob4585a776410cb353616c06894f0574f748f8505c
1 /*
2 * COPYRIGHT
4 * PCB, interactive printed circuit board design
5 * Copyright (C) 2004, 2007 Dan McMahill
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
27 #include <ctype.h>
28 #include <math.h>
29 #include <stdio.h>
31 #ifdef HAVE_STDLIB_H
32 #include <stdlib.h>
33 #endif
35 #ifdef HAVE_STRING_H
36 #include <string.h>
37 #endif
39 #ifdef HAVE_SYS_TYPES_H
40 #include <sys/types.h>
41 #endif
43 #ifdef HAVE_REGEX_H
44 #include <regex.h>
45 #else
46 #ifdef HAVE_UNISTD_H
47 #include <unistd.h>
48 #endif
49 #endif
51 #include "change.h"
52 #include "data.h"
53 #include "draw.h"
54 #include "error.h"
55 #include "global.h"
56 #include "resource.h"
57 #include "set.h"
58 #include "undo.h"
59 #include "vendor.h"
61 #ifdef HAVE_LIBDMALLOC
62 #include <dmalloc.h>
63 #endif
65 static void add_to_drills (char *);
66 static void apply_vendor_map (void);
67 static void process_skips (Resource *);
68 static bool rematch (const char *, const char *);
70 /* list of vendor drills and a count of them */
71 static int *vendor_drills = NULL;
72 static int n_vendor_drills = 0;
74 static int cached_drill = -1;
75 static int cached_map = -1;
77 /* lists of elements to ignore */
78 static char **ignore_refdes = NULL;
79 static int n_refdes = 0;
80 static char **ignore_value = NULL;
81 static int n_value = 0;
82 static char **ignore_descr = NULL;
83 static int n_descr = 0;
85 /* vendor name */
86 static char *vendor_name = NULL;
88 /* resource file to PCB units scale factor */
89 static double sf;
92 /* enable/disable mapping */
93 static bool vendorMapEnable = false;
95 /* type of drill mapping */
96 #define CLOSEST 1
97 #define ROUND_UP 0
98 static int rounding_method = ROUND_UP;
100 #define FREE(x) if((x) != NULL) { free (x) ; (x) = NULL; }
102 /* ************************************************************ */
104 static const char apply_vendor_syntax[] = "ApplyVendor()";
106 static const char apply_vendor_help[] =
107 "Applies the currently loaded vendor drill table to the current design.";
109 /* %start-doc actions ApplyVendor
110 @cindex vendor map
111 @cindex vendor drill table
112 @findex ApplyVendor()
114 This will modify all of your drill holes to match the list of allowed
115 sizes for your vendor.
116 %end-doc */
119 ActionApplyVendor (int argc, char **argv, Coord x, Coord y)
121 hid_action ("Busy");
122 apply_vendor_map ();
123 return 0;
126 /* ************************************************************ */
128 static const char toggle_vendor_syntax[] = "ToggleVendor()";
130 static const char toggle_vendor_help[] =
131 "Toggles the state of automatic drill size mapping.";
133 /* %start-doc actions ToggleVendor
135 @cindex vendor map
136 @cindex vendor drill table
137 @findex ToggleVendor()
139 When drill mapping is enabled, new instances of pins and vias will
140 have their drill holes mapped to one of the allowed drill sizes
141 specified in the currently loaded vendor drill table. To enable drill
142 mapping, a vendor resource file containing a drill table must be
143 loaded first.
145 %end-doc */
148 ActionToggleVendor (int argc, char **argv, Coord x, Coord y)
150 if (vendorMapEnable)
151 vendorMapEnable = false;
152 else
153 vendorMapEnable = true;
154 return 0;
157 /* ************************************************************ */
159 static const char enable_vendor_syntax[] = "EnableVendor()";
161 static const char enable_vendor_help[] =
162 "Enables automatic drill size mapping.";
164 /* %start-doc actions EnableVendor
166 @cindex vendor map
167 @cindex vendor drill table
168 @findex EnableVendor()
170 When drill mapping is enabled, new instances of pins and vias will
171 have their drill holes mapped to one of the allowed drill sizes
172 specified in the currently loaded vendor drill table. To enable drill
173 mapping, a vendor resource file containing a drill table must be
174 loaded first.
176 %end-doc */
179 ActionEnableVendor (int argc, char **argv, Coord x, Coord y)
181 vendorMapEnable = true;
182 return 0;
185 /* ************************************************************ */
187 static const char disable_vendor_syntax[] = "DisableVendor()";
189 static const char disable_vendor_help[] =
190 "Disables automatic drill size mapping.";
192 /* %start-doc actions DisableVendor
194 @cindex vendor map
195 @cindex vendor drill table
196 @findex DisableVendor()
198 When drill mapping is enabled, new instances of pins and vias will
199 have their drill holes mapped to one of the allowed drill sizes
200 specified in the currently loaded vendor drill table.
202 %end-doc */
205 ActionDisableVendor (int argc, char **argv, Coord x, Coord y)
207 vendorMapEnable = false;
208 return 0;
211 /* ************************************************************ */
213 static const char unload_vendor_syntax[] = "UnloadVendor()";
215 static const char unload_vendor_help[] =
216 "Unloads the current vendor drill mapping table.";
218 /* %start-doc actions UnloadVendor
220 @cindex vendor map
221 @cindex vendor drill table
222 @findex UnloadVendor()
224 %end-doc */
227 ActionUnloadVendor (int argc, char **argv, Coord x, Coord y)
229 cached_drill = -1;
231 /* Unload any vendor table we may have had */
232 n_vendor_drills = 0;
233 n_refdes = 0;
234 n_value = 0;
235 n_descr = 0;
236 FREE (vendor_drills);
237 FREE (ignore_refdes);
238 FREE (ignore_value);
239 FREE (ignore_descr);
240 return 0;
243 /* ************************************************************ */
245 static const char load_vendor_syntax[] = "LoadVendorFrom(filename)";
247 static const char load_vendor_help[] =
248 "Loads the specified vendor resource file.";
250 /* %start-doc actions LoadVendorFrom
252 @cindex vendor map
253 @cindex vendor drill table
254 @findex LoadVendorFrom()
256 @table @var
257 @item filename
258 Name of the vendor resource file. If not specified, the user will
259 be prompted to enter one.
260 @end table
262 %end-doc */
265 ActionLoadVendorFrom (int argc, char **argv, Coord x, Coord y)
267 int i;
268 char *fname = NULL;
269 static char *default_file = NULL;
270 char *sval;
271 Resource *res, *drcres, *drlres;
272 int type;
273 bool free_fname = false;
275 cached_drill = -1;
277 fname = argc ? argv[0] : 0;
279 if (!fname || !*fname)
281 fname = gui->fileselect (_("Load Vendor Resource File..."),
282 _("Picks a vendor resource file to load.\n"
283 "This file can contain drc settings for a\n"
284 "particular vendor as well as a list of\n"
285 "predefined drills which are allowed."),
286 default_file, ".res", "vendor",
287 HID_FILESELECT_READ);
288 if (fname == NULL)
289 AFAIL (load_vendor);
291 free_fname = true;
293 free (default_file);
294 default_file = NULL;
296 if (fname && *fname)
297 default_file = strdup (fname);
300 /* Unload any vendor table we may have had */
301 n_vendor_drills = 0;
302 n_refdes = 0;
303 n_value = 0;
304 n_descr = 0;
305 FREE (vendor_drills);
306 FREE (ignore_refdes);
307 FREE (ignore_value);
308 FREE (ignore_descr);
311 /* load the resource file */
312 res = resource_parse (fname, NULL);
313 if (res == NULL)
315 Message (_("Could not load vendor resource file \"%s\"\n"), fname);
316 return 1;
319 /* figure out the vendor name, if specified */
320 vendor_name = (char *)UNKNOWN (resource_value (res, "vendor"));
322 /* figure out the units, if specified */
323 sval = resource_value (res, "units");
324 if (sval == NULL)
326 sf = MIL_TO_COORD(1);
328 else if ((NSTRCMP (sval, "mil") == 0) || (NSTRCMP (sval, "mils") == 0))
330 sf = MIL_TO_COORD(1);
332 else if ((NSTRCMP (sval, "inch") == 0) || (NSTRCMP (sval, "inches") == 0))
334 sf = INCH_TO_COORD(1);
336 else if (NSTRCMP (sval, "mm") == 0)
338 sf = MM_TO_COORD(1);
340 else
342 Message ("\"%s\" is not a supported units. Defaulting to inch\n",
343 sval);
344 sf = INCH_TO_COORD(1);
348 /* default to ROUND_UP */
349 rounding_method = ROUND_UP;
351 /* extract the drillmap resource */
352 drlres = resource_subres (res, "drillmap");
353 if (drlres == NULL)
355 Message (_("No drillmap resource found\n"));
357 else
359 sval = resource_value (drlres, "round");
360 if (sval != NULL)
362 if (NSTRCMP (sval, "up") == 0)
364 rounding_method = ROUND_UP;
366 else if (NSTRCMP (sval, "nearest") == 0)
368 rounding_method = CLOSEST;
370 else
372 Message (_
373 ("\"%s\" is not a valid rounding type. Defaulting to up\n"),
374 sval);
375 rounding_method = ROUND_UP;
379 process_skips (resource_subres (drlres, "skips"));
381 for (i = 0; i < drlres->c; i++)
383 type = resource_type (drlres->v[i]);
384 switch (type)
386 case 10:
387 /* just a number */
388 add_to_drills (drlres->v[i].value);
389 break;
391 default:
392 break;
397 /* Extract the DRC resource */
398 drcres = resource_subres (res, "drc");
400 sval = resource_value (drcres, "copper_space");
401 if (sval != NULL)
403 PCB->Bloat = floor (sf * atof (sval) + 0.5);
404 Message (_("Set DRC minimum copper spacing to %.2f mils\n"),
405 0.01 * PCB->Bloat);
408 sval = resource_value (drcres, "copper_overlap");
409 if (sval != NULL)
411 PCB->Shrink = floor (sf * atof (sval) + 0.5);
412 Message (_("Set DRC minimum copper overlap to %.2f mils\n"),
413 0.01 * PCB->Shrink);
416 sval = resource_value (drcres, "copper_width");
417 if (sval != NULL)
419 PCB->minWid = floor (sf * atof (sval) + 0.5);
420 Message (_("Set DRC minimum copper spacing to %.2f mils\n"),
421 0.01 * PCB->minWid);
424 sval = resource_value (drcres, "silk_width");
425 if (sval != NULL)
427 PCB->minSlk = floor (sf * atof (sval) + 0.5);
428 Message (_("Set DRC minimum silk width to %.2f mils\n"),
429 0.01 * PCB->minSlk);
432 sval = resource_value (drcres, "min_drill");
433 if (sval != NULL)
435 PCB->minDrill = floor (sf * atof (sval) + 0.5);
436 Message (_("Set DRC minimum drill diameter to %.2f mils\n"),
437 0.01 * PCB->minDrill);
440 sval = resource_value (drcres, "min_ring");
441 if (sval != NULL)
443 PCB->minRing = floor (sf * atof (sval) + 0.5);
444 Message (_("Set DRC minimum annular ring to %.2f mils\n"),
445 0.01 * PCB->minRing);
448 Message (_("Loaded %d vendor drills from %s\n"), n_vendor_drills, fname);
449 Message (_("Loaded %d RefDes skips, %d Value skips, %d Descr skips\n"),
450 n_refdes, n_value, n_descr);
452 vendorMapEnable = true;
453 apply_vendor_map ();
454 if (free_fname)
455 free (fname);
456 return 0;
459 static void
460 apply_vendor_map (void)
462 int i;
463 int changed, tot;
464 bool state;
466 state = vendorMapEnable;
468 /* enable mapping */
469 vendorMapEnable = true;
471 /* reset our counts */
472 changed = 0;
473 tot = 0;
475 /* If we have loaded vendor drills, then apply them to the design */
476 if (n_vendor_drills > 0)
479 /* first all the vias */
480 VIA_LOOP (PCB->Data);
482 tot++;
483 if (via->DrillingHole != vendorDrillMap (via->DrillingHole))
485 /* only change unlocked vias */
486 if (!TEST_FLAG (LOCKFLAG, via))
488 if (ChangeObject2ndSize (VIA_TYPE, via, NULL, NULL,
489 vendorDrillMap (via->DrillingHole),
490 true, false))
491 changed++;
492 else
494 Message (_
495 ("Via at %.2f, %.2f not changed. Possible reasons:\n"
496 "\t- pad size too small\n"
497 "\t- new size would be too large or too small\n"),
498 0.01 * via->X, 0.01 * via->Y);
501 else
503 Message (_("Locked via at %.2f, %.2f not changed.\n"),
504 0.01 * via->X, 0.01 * via->Y);
508 END_LOOP;
510 /* and now the pins */
511 ELEMENT_LOOP (PCB->Data);
514 * first figure out if this element should be skipped for some
515 * reason
517 if (vendorIsElementMappable (element))
519 /* the element is ok to modify, so iterate over its pins */
520 PIN_LOOP (element);
522 tot++;
523 if (pin->DrillingHole != vendorDrillMap (pin->DrillingHole))
525 if (!TEST_FLAG (LOCKFLAG, pin))
527 if (ChangeObject2ndSize (PIN_TYPE, element, pin, NULL,
528 vendorDrillMap (pin->
529 DrillingHole),
530 true, false))
531 changed++;
532 else
534 Message (_
535 ("Pin %s (%s) at %.2f, %.2f (element %s, %s, %s) not changed.\n"
536 "\tPossible reasons:\n"
537 "\t- pad size too small\n"
538 "\t- new size would be too large or too small\n"),
539 UNKNOWN (pin->Number), UNKNOWN (pin->Name),
540 0.01 * pin->X, 0.01 * pin->Y,
541 UNKNOWN (NAMEONPCB_NAME (element)),
542 UNKNOWN (VALUE_NAME (element)),
543 UNKNOWN (DESCRIPTION_NAME (element)));
546 else
548 Message (_
549 ("Locked pin at %-6.2f, %-6.2f not changed.\n"),
550 0.01 * pin->X, 0.01 * pin->Y);
554 END_LOOP;
557 END_LOOP;
559 Message (_("Updated %d drill sizes out of %d total\n"), changed, tot);
561 /* Update the current Via */
562 if (Settings.ViaDrillingHole !=
563 vendorDrillMap (Settings.ViaDrillingHole))
565 changed++;
566 Settings.ViaDrillingHole =
567 vendorDrillMap (Settings.ViaDrillingHole);
568 Message (_("Adjusted active via hole size to be %6.2f mils\n"),
569 0.01 * Settings.ViaDrillingHole);
572 /* and update the vias for the various routing styles */
573 for (i = 0; i < NUM_STYLES; i++)
575 if (PCB->RouteStyle[i].Hole !=
576 vendorDrillMap (PCB->RouteStyle[i].Hole))
578 changed++;
579 PCB->RouteStyle[i].Hole =
580 vendorDrillMap (PCB->RouteStyle[i].Hole);
581 Message (_
582 ("Adjusted %s routing style via hole size to be %6.2f mils\n"),
583 PCB->RouteStyle[i].Name,
584 0.01 * PCB->RouteStyle[i].Hole);
585 if (PCB->RouteStyle[i].Diameter <
586 PCB->RouteStyle[i].Hole + MIN_PINORVIACOPPER)
588 PCB->RouteStyle[i].Diameter =
589 PCB->RouteStyle[i].Hole + MIN_PINORVIACOPPER;
590 Message (_
591 ("Increased %s routing style via diameter to %6.2f mils\n"),
592 PCB->RouteStyle[i].Name,
593 0.01 * PCB->RouteStyle[i].Diameter);
599 * if we've changed anything, indicate that we need to save the
600 * file, redraw things, and make sure we can undo.
602 if (changed)
604 SetChangedFlag (true);
605 Redraw ();
606 IncrementUndoSerialNumber ();
610 /* restore mapping on/off */
611 vendorMapEnable = state;
614 /* for a given drill size, find the closest vendor drill size */
616 vendorDrillMap (int in)
618 int i, min, max;
620 if (in == cached_drill)
621 return cached_map;
622 cached_drill = in;
624 /* skip the mapping if we don't have a vendor drill table */
625 if ((n_vendor_drills == 0) || (vendor_drills == NULL)
626 || (vendorMapEnable == false))
628 cached_map = in;
629 return in;
632 /* are we smaller than the smallest drill? */
633 if (in <= vendor_drills[0])
635 cached_map = vendor_drills[0];
636 return vendor_drills[0];
639 /* are we larger than the largest drill? */
640 if (in > vendor_drills[n_vendor_drills - 1])
642 Message (_("Vendor drill list does not contain a drill >= %6.2f mil\n"
643 "Using %6.2f mil instead.\n"),
644 0.01 * in, 0.01 * vendor_drills[n_vendor_drills - 1]);
645 cached_map = vendor_drills[n_vendor_drills - 1];
646 return vendor_drills[n_vendor_drills - 1];
649 /* figure out which 2 drills are closest in size */
650 min = 0;
651 max = n_vendor_drills - 1;
652 while (max - min > 1)
654 i = (max+min) / 2;
655 if (in > vendor_drills[i])
656 min = i;
657 else
658 max = i;
660 i = max;
662 /* now round per the rounding mode */
663 if (rounding_method == CLOSEST)
665 /* find the closest drill size */
666 if ((in - vendor_drills[i - 1]) > (vendor_drills[i] - in))
668 cached_map = vendor_drills[i];
669 return vendor_drills[i];
671 else
673 cached_map = vendor_drills[i - 1];
674 return vendor_drills[i - 1];
677 else
679 /* always round up */
680 cached_map = vendor_drills[i];
681 return vendor_drills[i];
686 /* add a drill size to the vendor drill list */
687 static void
688 add_to_drills (char *sval)
690 double tmpd;
691 int val;
692 int k, j;
694 /* increment the count and make sure we have memory */
695 n_vendor_drills++;
696 if ((vendor_drills = (int *)realloc (vendor_drills,
697 n_vendor_drills * sizeof (int))) == NULL)
699 fprintf (stderr, "realloc() failed to allocate %ld bytes\n",
700 (unsigned long) n_vendor_drills * sizeof (int));
701 return;
704 /* string to a value with the units scale factor in place */
705 tmpd = atof (sval);
706 val = floor (sf * tmpd + 0.5);
709 * We keep the array of vendor drills sorted to make it easier to
710 * do the rounding later. The algorithm used here is not so efficient,
711 * but we're not dealing with much in the way of data.
714 /* figure out where to insert the value to keep the array sorted. */
715 k = 0;
716 while ((k < n_vendor_drills - 1) && (vendor_drills[k] < val))
717 k++;
719 if (k == n_vendor_drills - 1)
721 vendor_drills[n_vendor_drills - 1] = val;
723 else
725 /* move up the existing drills to make room */
726 for (j = n_vendor_drills - 1; j > k; j--)
728 vendor_drills[j] = vendor_drills[j - 1];
731 vendor_drills[k] = val;
735 /* deal with the "skip" subresource */
736 static void
737 process_skips (Resource * res)
739 int type;
740 int i, k;
741 char *sval;
742 int *cnt;
743 char ***lst = NULL;
745 if (res == NULL)
746 return;
748 for (i = 0; i < res->c; i++)
750 type = resource_type (res->v[i]);
751 switch (type)
753 case 1:
755 * an unnamed sub resource. This is something like
756 * {refdes "J3"}
758 sval = res->v[i].subres->v[0].value;
759 if (sval == NULL)
761 Message ("Error: null skip value\n");
763 else
765 if (NSTRCMP (sval, "refdes") == 0)
767 cnt = &n_refdes;
768 lst = &ignore_refdes;
770 else if (NSTRCMP (sval, "value") == 0)
772 cnt = &n_value;
773 lst = &ignore_value;
775 else if (NSTRCMP (sval, "descr") == 0)
777 cnt = &n_descr;
778 lst = &ignore_descr;
780 else
782 cnt = NULL;
785 /* add the entry to the appropriate list */
786 if (cnt != NULL)
788 for (k = 1; k < res->v[i].subres->c; k++)
790 sval = res->v[i].subres->v[k].value;
791 (*cnt)++;
792 if ((*lst =
793 (char **) realloc (*lst,
794 (*cnt) * sizeof (char *))) ==
795 NULL)
797 fprintf (stderr, "realloc() failed\n");
798 exit (-1);
800 (*lst)[*cnt - 1] = strdup (sval);
804 break;
806 default:
807 Message (_("Ignored resource type = %d in skips= section\n"), type);
813 bool
814 vendorIsElementMappable (ElementType *element)
816 int i;
817 int noskip;
819 if (vendorMapEnable == false)
820 return false;
822 noskip = 1;
823 for (i = 0; i < n_refdes; i++)
825 if ((NSTRCMP (UNKNOWN (NAMEONPCB_NAME (element)), ignore_refdes[i]) ==
827 || rematch (ignore_refdes[i], UNKNOWN (NAMEONPCB_NAME (element))))
829 Message (_
830 ("Vendor mapping skipped because refdes = %s matches %s\n"),
831 UNKNOWN (NAMEONPCB_NAME (element)), ignore_refdes[i]);
832 noskip = 0;
835 if (noskip)
836 for (i = 0; i < n_value; i++)
838 if ((NSTRCMP (UNKNOWN (VALUE_NAME (element)), ignore_value[i]) == 0)
839 || rematch (ignore_value[i], UNKNOWN (VALUE_NAME (element))))
841 Message (_
842 ("Vendor mapping skipped because value = %s matches %s\n"),
843 UNKNOWN (VALUE_NAME (element)), ignore_value[i]);
844 noskip = 0;
848 if (noskip)
849 for (i = 0; i < n_descr; i++)
851 if ((NSTRCMP (UNKNOWN (DESCRIPTION_NAME (element)), ignore_descr[i])
852 == 0)
853 || rematch (ignore_descr[i],
854 UNKNOWN (DESCRIPTION_NAME (element))))
856 Message (_
857 ("Vendor mapping skipped because descr = %s matches %s\n"),
858 UNKNOWN (DESCRIPTION_NAME (element)), ignore_descr[i]);
859 noskip = 0;
863 if (noskip && TEST_FLAG (LOCKFLAG, element))
865 Message (_("Vendor mapping skipped because element %s is locked\n"),
866 UNKNOWN (NAMEONPCB_NAME (element)));
867 noskip = 0;
870 if (noskip)
871 return true;
872 else
873 return false;
876 static bool
877 rematch (const char *re, const char *s)
880 * If this system has regular expression capability, then
881 * add support for regular expressions in the skip lists.
884 #if defined(HAVE_REGCOMP)
886 int result;
887 regmatch_t match;
888 regex_t compiled;
890 /* compile the regular expression */
891 result = regcomp (&compiled, re, REG_EXTENDED | REG_ICASE | REG_NOSUB);
892 if (result)
894 char errorstring[128];
896 regerror (result, &compiled, errorstring, sizeof (errorstring));
897 Message ("regexp error: %s\n", errorstring);
898 regfree (&compiled);
899 return (false);
902 result = regexec (&compiled, s, 1, &match, 0);
903 regfree (&compiled);
905 if (result == 0)
906 return (true);
907 else
908 return (false);
910 #elif defined(HAVE_RE_COMP)
911 int m;
912 char *rslt;
914 /* compile the regular expression */
915 if ((rslt = re_comp (re)) != NULL)
917 Message ("re_comp error: %s\n", rslt);
918 return (false);
921 m = re_exec (s);
923 switch m
925 case 1:
926 return (true);
927 break;
929 case 0:
930 return (false);
931 break;
933 default:
934 Message ("re_exec error\n");
935 break;
938 #else
939 return (false);
940 #endif
944 HID_Action vendor_action_list[] = {
945 {"ApplyVendor", 0, ActionApplyVendor,
946 apply_vendor_help, apply_vendor_syntax}
948 {"ToggleVendor", 0, ActionToggleVendor,
949 toggle_vendor_help, toggle_vendor_syntax}
951 {"EnableVendor", 0, ActionEnableVendor,
952 enable_vendor_help, enable_vendor_syntax}
954 {"DisableVendor", 0, ActionDisableVendor,
955 disable_vendor_help, disable_vendor_syntax}
957 {"UnloadVendor", 0, ActionUnloadVendor,
958 unload_vendor_help, unload_vendor_syntax}
960 {"LoadVendorFrom", 0, ActionLoadVendorFrom,
961 load_vendor_help, load_vendor_syntax}
964 REGISTER_ACTIONS (vendor_action_list)
966 static int vendor_get_enabled (void *data)
968 return vendorMapEnable;
971 HID_Flag vendor_flag_list[] = {
972 {"VendorMapOn", vendor_get_enabled, NULL}
975 REGISTER_FLAGS (vendor_flag_list)