pcb 4.1.1
An interactive printed circuit board layout editor.

hid_resource.c

Go to the documentation of this file.
00001 #include <string.h>
00002 #include <stdlib.h>
00003 #include <errno.h>
00004 
00005 #include "global.h"
00006 #include "hid.h"
00007 #include "resource.h"
00008 #include "hid/common/hid_resource.h"
00009 
00010 /* #define DEBUG_HID_RESOURCE */
00011 
00012 static int button_count;   // number of buttons we have actions for
00013 static int *button_nums;   // list of button numbers
00014 static int *mod_count;     // how many mods they have
00015 static unsigned *mods;     // mods, in order, one button after another
00016 static Resource** actions; // actions, in order, one button after another
00017 
00018 static Resource *
00019 res_wrap (char *value)
00020 {
00021   Resource *tmp;
00022   tmp = resource_create (0);
00023   resource_add_val (tmp, 0, value, 0);
00024   return tmp;
00025 }
00026 
00027 static unsigned
00028 parse_mods (char *value)
00029 {
00030   unsigned m = 0;
00031   long int mod_num;
00032   char *s;
00033 
00034   for (s=value; *s; s++)
00035     *s = tolower(*s);
00036 
00037   s = strstr(value, "mod");
00038   if (s)
00039     {
00040       s += 3; // skip "mod" to get to number
00041       errno = 0;
00042       mod_num = strtol(s, (char**) NULL, 0);
00043       if (!errno)
00044         m |= M_Mod(mod_num);
00045     }
00046   if (strstr(value, "shift"))
00047     m |= M_Shift;
00048   if (strstr(value, "ctrl"))
00049     m |= M_Ctrl;
00050   if (strstr(value, "alt"))
00051     m |= M_Alt;
00052   if (strstr(value, "up"))
00053     m |= M_Release;
00054   return m;
00055 }
00056 
00057 static int
00058 button_name_to_num (const char *name)
00059 {
00060   /* All mouse-related resources must be named.  The name is the
00061      mouse button number.  */
00062   if (!name)
00063     return -1;
00064   else if (strcasecmp (name, "left") == 0)
00065     return 1;
00066   else if (strcasecmp (name, "middle") == 0)
00067     return 2;
00068   else if (strcasecmp (name, "right") == 0)
00069     return 3;
00070   else if (strcasecmp (name, "up") == 0)
00071     return 4;
00072   else if (strcasecmp (name, "down") == 0)
00073     return 5;
00074   else if (strcasecmp (name, "scroll-left") == 0)
00075     return 6;
00076   else if (strcasecmp (name, "scroll-right") == 0)
00077     return 7;
00078   else
00079     return atoi (name);
00080 }
00081 
00082 void
00083 load_mouse_resource (const Resource *res)
00084 {
00085   int bi, mi, a;
00086   int action_count;
00087 #ifdef DEBUG_HID_RESOURCE
00088   fprintf(stderr, "note mouse resource:\n");
00089   resource_dump (res);
00090 #endif
00091 
00092   button_count = res->c;
00093   button_nums = (int *)malloc(res->c * sizeof(int));
00094   mod_count = (int *)malloc(res->c * sizeof(int));
00095   action_count = 0;
00096   for (bi=0; bi<res->c; bi++)
00097     {
00098       if (res->v[bi].value)
00099         action_count++;
00100 
00101       if (res->v[bi].subres)
00102         action_count += res->v[bi].subres->c;
00103 
00104     }
00105   mods = (unsigned int *)malloc(action_count * sizeof(int));
00106   actions = (Resource **)malloc(action_count * sizeof(Resource*));
00107 
00108   a = 0;
00109   for (bi=0; bi<res->c; bi++)
00110     {
00111       int button_num = button_name_to_num(res->v[bi].name);
00112 
00113       if (button_num < 0)
00114         continue;
00115 
00116       button_nums[bi] = button_num;
00117       mod_count[bi] = 0;
00118 
00119       if (res->v[bi].value)
00120         {
00121           mods[a] = 0;
00122           actions[a++] = res_wrap (res->v[bi].value);         
00123           mod_count[bi] = 1;
00124         }
00125 
00126       if (res->v[bi].subres)
00127         {
00128           Resource *m = res->v[bi].subres;
00129           mod_count[bi] += m->c;
00130 
00131           for (mi=0; mi<m->c; mi++, a++)
00132             {
00133               switch (resource_type (m->v[mi]))
00134                 {
00135                 case 1: /* subres only */
00136                   mods[a] = 0;
00137                   actions[a] = m->v[mi].subres;
00138                   break;
00139 
00140                 case 10: /* value only */
00141                   mods[a] = 0;
00142                   actions[a] = res_wrap (m->v[mi].value);
00143                   break;
00144 
00145                 case 101: /* name = subres */
00146                   mods[a] = parse_mods (m->v[mi].name);
00147                   actions[a] = m->v[mi].subres;
00148                   break;
00149 
00150                 case 110: /* name = value */
00151                   mods[a] = parse_mods (m->v[mi].name);
00152                   actions[a] = res_wrap (m->v[mi].value);
00153                   break;
00154                 }
00155             }
00156         }
00157     }
00158 }
00159 
00160 static Resource*
00161 find_best_action (int button, int start, unsigned mod_mask)
00162 {
00163   int i, j;
00164   int count = mod_count[button];
00165   unsigned search_mask = mod_mask & ~M_Release;
00166   unsigned release_mask = mod_mask & M_Release;
00167 
00168   // look for exact mod match
00169   for (i=start; i<start+count; i++)
00170     if (mods[i] == mod_mask) {
00171       return actions[i];
00172     }
00173 
00174   for (j=search_mask-1; j>=0; j--)
00175     if ((j & search_mask) == j) // this would work
00176       for (i=start; i<start+count; i++) // search for it
00177         if (mods[i] == (j | release_mask))
00178           return actions[i];
00179 
00180   return NULL;
00181 }
00182 
00183 void
00184 do_mouse_action (int button, int mod_mask)
00185 {
00186   Resource *action = NULL;
00187   int bi, i, a;
00188 
00189   // find the right set of actions;
00190   a = 0;
00191   for (bi=0; bi<button_count && !action; bi++)
00192     if (button_nums[bi] == button)
00193       {
00194         action = find_best_action(bi, a, mod_mask);
00195         break;
00196       }
00197     else
00198       a += mod_count[bi]; // skip this buttons actions
00199 
00200   if (!action)
00201     return;
00202 
00203   for (i = 0; i < action->c; i++)
00204     if (action->v[i].value)
00205       if (hid_parse_actions (action->v[i].value))
00206         return;
00207 }