/[rdesktop]/sourceforge.net/trunk/rdesktop/xkeymap.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/xkeymap.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 64 by astrand, Thu Jul 18 16:38:31 2002 UTC revision 115 by astrand, Wed Sep 11 09:52:30 2002 UTC
# Line 23  Line 23 
23  #include <stdio.h>  #include <stdio.h>
24  #include <stdlib.h>  #include <stdlib.h>
25  #include <string.h>  #include <string.h>
26    #include <ctype.h>
27  #include <limits.h>  #include <limits.h>
28  #include "rdesktop.h"  #include "rdesktop.h"
29    #include "scancodes.h"
30    
31  #define KEYMAP_SIZE 4096  #define KEYMAP_SIZE 4096
32  #define KEYMAP_MASK (KEYMAP_SIZE - 1)  #define KEYMAP_MASK (KEYMAP_SIZE - 1)
33    #define KEYMAP_MAX_LINE_LENGTH 80
34    
35  extern Display *display;  extern Display *display;
36  extern char keymapname[16];  extern char keymapname[16];
37  extern int keylayout;  extern int keylayout;
38    extern BOOL enable_compose;
39    
40    static key_translation keymap[KEYMAP_SIZE];
41    static int min_keycode;
42    static uint16 remote_modifier_state = 0;
43    
44    static void update_modifier_state(uint16 modifiers, BOOL pressed);
45    
46    static void
47    add_to_keymap(char *keyname, uint8 scancode, uint16 modifiers, char *mapname)
48    {
49            KeySym keysym;
50    
51            keysym = XStringToKeysym(keyname);
52            if (keysym == NoSymbol)
53            {
54                    error("Bad keysym %s in keymap %s\n", keyname, mapname);
55                    return;
56            }
57    
58            DEBUG_KBD(("Adding translation, keysym=0x%x, scancode=0x%x, "
59                       "modifiers=0x%x\n", (unsigned int) keysym, scancode, modifiers));
60    
61            keymap[keysym & KEYMAP_MASK].scancode = scancode;
62            keymap[keysym & KEYMAP_MASK].modifiers = modifiers;
63    
64            return;
65    }
66    
 static uint8 keymap[KEYMAP_SIZE];  
 static unsigned int min_keycode;  
67    
68  static BOOL  static BOOL
69  xkeymap_read(char *mapname)  xkeymap_read(char *mapname)
70  {  {
71          FILE *fp;          FILE *fp;
72          char line[PATH_MAX], path[PATH_MAX];          char line[KEYMAP_MAX_LINE_LENGTH], path[PATH_MAX];
73            unsigned int line_num = 0;
74            unsigned int line_length = 0;
75          char *keyname, *p;          char *keyname, *p;
76          KeySym keysym;          char *line_rest;
77          unsigned char keycode;          uint8 scancode;
78            uint16 modifiers;
79    
80    
81          strcpy(path, KEYMAP_PATH);          strcpy(path, KEYMAP_PATH);
82          strncat(path, mapname, sizeof(path) - sizeof(KEYMAP_PATH));          strncat(path, mapname, sizeof(path) - sizeof(KEYMAP_PATH));
# Line 55  xkeymap_read(char *mapname) Line 88  xkeymap_read(char *mapname)
88                  return False;                  return False;
89          }          }
90    
91            /* FIXME: More tolerant on white space */
92          while (fgets(line, sizeof(line), fp) != NULL)          while (fgets(line, sizeof(line), fp) != NULL)
93          {          {
94                    line_num++;
95    
96                    /* Replace the \n with \0 */
97                  p = strchr(line, '\n');                  p = strchr(line, '\n');
98                  if (p != NULL)                  if (p != NULL)
99                          *p = 0;                          *p = 0;
100    
101                  keycode = strtol(line, &keyname, 16);                  line_length = strlen(line);
                 if ((keycode != 0) && (*keyname == ' '))  
                 {  
                         do  
                         {  
                                 keyname++;  
                                 p = strchr(keyname, ' ');  
                                 if (p != NULL)  
                                         *p = 0;  
   
                                 keysym = XStringToKeysym(keyname);  
                                 if (keysym == NoSymbol)  
                                         error("Bad keysym %s in keymap %s\n",  
                                               keyname, mapname);  
102    
103                                  keymap[keysym & KEYMAP_MASK] = keycode;                  /* Completely empty line */
104                                  keyname = p;                  if (strspn(line, " \t\n\r\f\v") == line_length)
105                    {
106                          }                          continue;
                         while (keyname != NULL);  
107                  }                  }
108                  else if (strncmp(line, "include ", 8) == 0)  
109                    /* Include */
110                    if (strncmp(line, "include ", 8) == 0)
111                  {                  {
112                          if (!xkeymap_read(line + 8))                          if (!xkeymap_read(line + 8))
113                                  return False;                                  return False;
114                            continue;
115                  }                  }
116                  else if (strncmp(line, "map ", 4) == 0)  
117                    /* map */
118                    if (strncmp(line, "map ", 4) == 0)
119                  {                  {
120                          keylayout = strtol(line + 4, NULL, 16);                          keylayout = strtol(line + 4, NULL, 16);
121                            DEBUG_KBD(("Keylayout 0x%x\n", keylayout));
122                            continue;
123                  }                  }
124                  else if (line[0] != '#')  
125                    /* compose */
126                    if (strncmp(line, "enable_compose", 15) == 0)
127                    {
128                            DEBUG_KBD(("Enabling compose handling\n"));
129                            enable_compose = True;
130                            continue;
131                    }
132    
133                    /* Comment */
134                    if (line[0] == '#')
135                  {                  {
136                          error("Malformed line in keymap %s\n", mapname);                          continue;
137                    }
138    
139                    /* Normal line */
140                    keyname = line;
141                    p = strchr(line, ' ');
142                    if (p == NULL)
143                    {
144                            error("Bad line %d in keymap %s\n", line_num, mapname);
145                            continue;
146                    }
147                    else
148                    {
149                            *p = 0;
150                    }
151    
152                    /* scancode */
153                    p++;
154                    scancode = strtol(p, &line_rest, 16);
155    
156                    /* flags */
157                    /* FIXME: Should allow case-insensitive flag names.
158                       Fix by using lex+yacc... */
159                    modifiers = 0;
160                    if (strstr(line_rest, "altgr"))
161                    {
162                            MASK_ADD_BITS(modifiers, MapAltGrMask);
163                    }
164    
165                    if (strstr(line_rest, "shift"))
166                    {
167                            MASK_ADD_BITS(modifiers, MapLeftShiftMask);
168                    }
169    
170                    if (strstr(line_rest, "numlock"))
171                    {
172                            MASK_ADD_BITS(modifiers, MapNumLockMask);
173                    }
174    
175                    if (strstr(line_rest, "localstate"))
176                    {
177                            MASK_ADD_BITS(modifiers, MapLocalStateMask);
178                    }
179    
180                    add_to_keymap(keyname, scancode, modifiers, mapname);
181    
182                    if (strstr(line_rest, "addupper"))
183                    {
184                            /* Automatically add uppercase key, with same modifiers
185                               plus shift */
186                            for (p = keyname; *p; p++)
187                                    *p = toupper(*p);
188                            MASK_ADD_BITS(modifiers, MapLeftShiftMask);
189                            add_to_keymap(keyname, scancode, modifiers, mapname);
190                  }                  }
191          }          }
192    
# Line 101  xkeymap_read(char *mapname) Line 194  xkeymap_read(char *mapname)
194          return True;          return True;
195  }  }
196    
197    
198    /* Before connecting and creating UI */
199  void  void
200  xkeymap_init(void)  xkeymap_init1(void)
201  {  {
202          unsigned int max_keycode;          int i;
203    
204          XDisplayKeycodes(display, &min_keycode, &max_keycode);          /* Zeroing keymap */
205            for (i = 0; i < KEYMAP_SIZE; i++)
206            {
207                    keymap[i].scancode = 0;
208                    keymap[i].modifiers = 0;
209            }
210    
211          if (strcmp(keymapname, "none"))          if (strcmp(keymapname, "none"))
212            {
213                  xkeymap_read(keymapname);                  xkeymap_read(keymapname);
214            }
215    
216  }  }
217    
218  uint8  /* After connecting and creating UI */
219  xkeymap_translate_key(unsigned int keysym, unsigned int keycode,  void
220                        uint16 * flags)  xkeymap_init2(void)
221  {  {
222          uint8 scancode;          unsigned int max_keycode;
223            XDisplayKeycodes(display, &min_keycode, (int *) &max_keycode);
224    }
225    
226    
227          scancode = keymap[keysym & KEYMAP_MASK];  key_translation
228          if (scancode != 0)  xkeymap_translate_key(KeySym keysym, unsigned int keycode, unsigned int state)
229    {
230            key_translation tr = { 0, 0 };
231    
232            tr = keymap[keysym & KEYMAP_MASK];
233    
234            if (tr.modifiers & MapLocalStateMask)
235          {          {
236                  if (scancode & 0x80)                  /* The modifiers to send for this key should be obtained
237                          *flags |= KBD_FLAG_EXT;                     from the local state. Currently, only shift is implemented. */
238                    if (state & ShiftMask)
239                    {
240                            tr.modifiers = MapLeftShiftMask;
241                    }
242            }
243    
244                  return (scancode & 0x7f);          if (tr.scancode != 0)
245            {
246                    DEBUG_KBD
247                            (("Found key translation, scancode=0x%x, modifiers=0x%x\n",
248                              tr.scancode, tr.modifiers));
249                    return tr;
250          }          }
251    
252          /* not in keymap, try to interpret the raw scancode */          fprintf(stderr, "No translation for (keysym 0x%lx, %s)\n", keysym, get_ksname(keysym));
253    
254            /* not in keymap, try to interpret the raw scancode */
255          if ((keycode >= min_keycode) && (keycode <= 0x60))          if ((keycode >= min_keycode) && (keycode <= 0x60))
                 return (uint8) (keycode - min_keycode);  
   
         *flags |= KBD_FLAG_EXT;  
   
         switch (keycode)  
256          {          {
257                  case 0x61:      /* home */                  tr.scancode = keycode - min_keycode;
258                          return 0x47;                  fprintf(stderr, "Sending guessed scancode 0x%x\n", tr.scancode);
259                  case 0x62:      /* up arrow */          }
260                          return 0x48;          else
261                  case 0x63:      /* page up */          {
262                          return 0x49;                  fprintf(stderr, "No good guess for keycode 0x%x found\n", keycode);
                 case 0x64:      /* left arrow */  
                         return 0x4b;  
                 case 0x66:      /* right arrow */  
                         return 0x4d;  
                 case 0x67:      /* end */  
                         return 0x4f;  
                 case 0x68:      /* down arrow */  
                         return 0x50;  
                 case 0x69:      /* page down */  
                         return 0x51;  
                 case 0x6a:      /* insert */  
                         return 0x52;  
                 case 0x6b:      /* delete */  
                         return 0x53;  
                 case 0x6c:      /* keypad enter */  
                         return 0x1c;  
                 case 0x6d:      /* right ctrl */  
                         return 0x1d;  
                 case 0x6f:      /* ctrl - print screen */  
                         return 0x37;  
                 case 0x70:      /* keypad '/' */  
                         return 0x35;  
                 case 0x71:      /* right alt */  
                         return 0x38;  
                 case 0x72:      /* ctrl break */  
                         return 0x46;  
                 case 0x73:      /* left window key */  
                         return 0x5b;  
                 case 0x74:      /* right window key */  
                         return 0x5c;  
                 case 0x75:      /* menu key */  
                         return 0x5d;  
263          }          }
264    
265          return 0;          return tr;
266  }  }
267    
268  uint16  uint16
# Line 198  xkeymap_translate_button(unsigned int bu Line 284  xkeymap_translate_button(unsigned int bu
284    
285          return 0;          return 0;
286  }  }
287    
288    char *
289    get_ksname(KeySym keysym)
290    {
291            char *ksname = NULL;
292    
293            if (keysym == NoSymbol)
294                    ksname = "NoSymbol";
295            else if (!(ksname = XKeysymToString(keysym)))
296                    ksname = "(no name)";
297    
298            return ksname;
299    }
300    
301    BOOL
302    inhibit_key(KeySym keysym)
303    {
304            switch (keysym)
305            {
306                    case XK_Caps_Lock:
307                            return True;
308                            break;
309                    case XK_Multi_key:
310                            return True;
311                            break;
312                    case XK_Num_Lock:
313                            return True;
314                            break;
315                    default:
316                            break;
317            }
318            return False;
319    }
320    
321    void
322    ensure_remote_modifiers(uint32 ev_time, key_translation tr)
323    {
324            /* If this key is a modifier, do nothing */
325            switch (tr.scancode)
326            {
327                    case SCANCODE_CHAR_LSHIFT:
328                    case SCANCODE_CHAR_RSHIFT:
329                    case SCANCODE_CHAR_LCTRL:
330                    case SCANCODE_CHAR_RCTRL:
331                    case SCANCODE_CHAR_LALT:
332                    case SCANCODE_CHAR_RALT:
333                    case SCANCODE_CHAR_LWIN:
334                    case SCANCODE_CHAR_RWIN:
335                    case SCANCODE_CHAR_NUMLOCK:
336                            return;
337                    default:
338                            break;
339            }
340    
341            /* Shift */
342            if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)
343                != MASK_HAS_BITS(remote_modifier_state, MapShiftMask))
344            {
345                    /* The remote modifier state is not correct */
346                    if (MASK_HAS_BITS(tr.modifiers, MapShiftMask))
347                    {
348                            /* Needs this modifier. Send down. */
349                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LSHIFT);
350                    }
351                    else
352                    {
353                            /* Should not use this modifier. Send up. */
354                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
355                    }
356            }
357    
358            /* AltGr */
359            if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask)
360                != MASK_HAS_BITS(remote_modifier_state, MapAltGrMask))
361            {
362                    /* The remote modifier state is not correct */
363                    if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask))
364                    {
365                            /* Needs this modifier. Send down. */
366                            rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RALT);
367                    }
368                    else
369                    {
370                            /* Should not use this modifier. Send up. */
371                            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
372                    }
373            }
374    
375            /* NumLock */
376            if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask)
377                != MASK_HAS_BITS(remote_modifier_state, MapNumLockMask))
378            {
379                    /* The remote modifier state is not correct */
380                    uint16 new_remote_state = 0;
381    
382                    if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask))
383                    {
384                            DEBUG_KBD(("Remote NumLock state is incorrect, activating NumLock.\n"));
385                            new_remote_state |= KBD_FLAG_NUMLOCK;
386                    }
387                    else
388                    {
389                            DEBUG_KBD(("Remote NumLock state is incorrect, deactivating NumLock.\n"));
390                    }
391    
392                    rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, new_remote_state, 0);
393                    update_modifier_state(SCANCODE_CHAR_NUMLOCK, True);
394            }
395    }
396    
397    
398    static void
399    update_modifier_state(uint16 modifiers, BOOL pressed)
400    {
401    #ifdef WITH_DEBUG_KBD
402            uint16 old_modifier_state;
403    
404            old_modifier_state = remote_modifier_state;
405    #endif
406    
407            switch (modifiers)
408            {
409                    case SCANCODE_CHAR_LSHIFT:
410                            MASK_CHANGE_BIT(remote_modifier_state, MapLeftShiftMask, pressed);
411                            break;
412                    case SCANCODE_CHAR_RSHIFT:
413                            MASK_CHANGE_BIT(remote_modifier_state, MapRightShiftMask, pressed);
414                            break;
415                    case SCANCODE_CHAR_LCTRL:
416                            MASK_CHANGE_BIT(remote_modifier_state, MapLeftCtrlMask, pressed);
417                            break;
418                    case SCANCODE_CHAR_RCTRL:
419                            MASK_CHANGE_BIT(remote_modifier_state, MapRightCtrlMask, pressed);
420                            break;
421                    case SCANCODE_CHAR_LALT:
422                            MASK_CHANGE_BIT(remote_modifier_state, MapLeftAltMask, pressed);
423                            break;
424                    case SCANCODE_CHAR_RALT:
425                            MASK_CHANGE_BIT(remote_modifier_state, MapRightAltMask, pressed);
426                            break;
427                    case SCANCODE_CHAR_LWIN:
428                            MASK_CHANGE_BIT(remote_modifier_state, MapLeftWinMask, pressed);
429                            break;
430                    case SCANCODE_CHAR_RWIN:
431                            MASK_CHANGE_BIT(remote_modifier_state, MapRightWinMask, pressed);
432                            break;
433                    case SCANCODE_CHAR_NUMLOCK:
434                            /* KeyReleases for NumLocks are sent immediately. Toggle the
435                               modifier state only on Keypress */
436                            if (pressed)
437                            {
438                                    BOOL newNumLockState;
439                                    newNumLockState =
440                                            (MASK_HAS_BITS
441                                             (remote_modifier_state, MapNumLockMask) == False);
442                                    MASK_CHANGE_BIT(remote_modifier_state,
443                                                    MapNumLockMask, newNumLockState);
444                            }
445                            break;
446            }
447    
448    #ifdef WITH_DEBUG_KBD
449            if (old_modifier_state != remote_modifier_state)
450            {
451                    DEBUG_KBD(("Before updating modifier_state:0x%x, pressed=0x%x\n",
452                               old_modifier_state, pressed));
453                    DEBUG_KBD(("After updating modifier_state:0x%x\n", remote_modifier_state));
454            }
455    #endif
456    
457    }
458    
459    /* Send keyboard input */
460    void
461    rdp_send_scancode(uint32 time, uint16 flags, uint16 scancode)
462    {
463            update_modifier_state(scancode, !(flags & RDP_KEYRELEASE));
464    
465            if (scancode & SCANCODE_EXTENDED)
466            {
467                    DEBUG_KBD(("Sending extended scancode=0x%x, flags=0x%x\n",
468                               scancode & ~SCANCODE_EXTENDED, flags));
469                    rdp_send_input(time, RDP_INPUT_SCANCODE, flags | KBD_FLAG_EXT,
470                                   scancode & ~SCANCODE_EXTENDED, 0);
471            }
472            else
473            {
474                    DEBUG_KBD(("Sending scancode=0x%x, flags=0x%x\n", scancode, flags));
475                    rdp_send_input(time, RDP_INPUT_SCANCODE, flags, scancode, 0);
476            }
477    }

Legend:
Removed from v.64  
changed lines
  Added in v.115

  ViewVC Help
Powered by ViewVC 1.1.26