1 /*
2   xrus - keyboard switcher/indicator
3   Copyright (c) 1996 Alexander V. Lukyanov
4   This is free software with no warranty.
5   See COPYING for details.
6 */
7 #include <config.h>
8 #include <stdio.h>
9 
10 #include <X11/Xlib.h>
11 #include <X11/Intrinsic.h>
12 
13 #include "keycomb.h"
14 #include "xrus.h"
15 
16 #include "xalloca.h"
17 
ParseKeyCombination(const char * str,struct KeyCombination * kc,char * err)18 void  ParseKeyCombination(const char *str,struct KeyCombination *kc,char *err)
19 {
20    char  *plus;
21    char  *scan;
22    KeySym   ks;
23    int   i;
24 
25    scan=alloca(strlen(str)+1);
26    strcpy(scan,str);
27 
28    kc->KeysNum=0;
29    err[0]=0;
30    for(;;)
31    {
32       plus=strchr(scan,'+');
33       if(plus==NULL)
34       {
35          if(*scan==0)
36             break;
37       }
38       else
39       {
40          *plus=0;
41       }
42       ks=XStringToKeysym(scan);
43       if(ks==NoSymbol)
44       {
45          sprintf(err+strlen(err),"Invalid key name (%s)\n",scan);
46       }
47       else
48       {
49          for(i=0; i<kc->KeysNum; i++)
50          {
51             if(kc->Keys[i]==ks)
52                break;
53          }
54          if(i==kc->KeysNum)
55          {
56             if(kc->KeysNum==sizeof(kc->Keys)/sizeof(kc->Keys[0]))
57             {
58                sprintf(err+strlen(err),"Too much keys\n");
59                break;
60             }
61             kc->Keys[kc->KeysNum++]=ks;
62          }
63       }
64       if(plus!=NULL)
65          scan=plus+1;
66       else
67          break;
68    }
69    kc->KeysPressed=0;
70    kc->KeysArmed=0;
71 }
72 
KeyCombinationProcessKeyPress(struct KeyCombination * kc,KeySym ks)73 void  KeyCombinationProcessKeyPress(struct KeyCombination *kc,KeySym ks)
74 {
75    int      oldKeysPressed;
76    int      i;
77 
78    oldKeysPressed=kc->KeysPressed;
79    for(i=0; i<kc->KeysNum; i++)
80    {
81       if(kc->Keys[i]==ks)
82          kc->KeysPressed|=(1<<i);
83    }
84    if(kc->KeysPressed!=oldKeysPressed && kc->KeysPressed==(1<<kc->KeysNum)-1)
85       kc->KeysArmed=1;
86    else
87       kc->KeysArmed=0;
88 }
89 
KeyCombinationProcessKeyRelease(struct KeyCombination * kc,KeySym ks,int fire)90 int   KeyCombinationProcessKeyRelease(struct KeyCombination *kc,KeySym ks,int fire)
91 {
92    int      oldKeysPressed;
93    int      i;
94 
95    oldKeysPressed=kc->KeysPressed;
96    for(i=0; i<kc->KeysNum; i++)
97    {
98       if(kc->Keys[i]==ks)
99          kc->KeysPressed&=~(1<<i);
100    }
101    i=0;
102    if(kc->KeysPressed!=oldKeysPressed && oldKeysPressed==(1<<kc->KeysNum)-1 && kc->KeysArmed)
103    {
104       if(fire && kc->Fire)
105          kc->Fire();
106       i=1;
107    }
108    kc->KeysArmed=0;
109    return i;
110 }
111 
PrintParseErrors(const char * resource,char * err)112 void  PrintParseErrors(const char *resource,char *err)
113 {
114    if(*err)
115    {
116       char *nl=err-1;
117       char *nl1;
118       while((nl1=strchr(nl+1,'\n'))!=NULL)
119       {
120          *nl1=0;
121          fprintf(stderr,"%s: %s parse error: %s\n",program,resource,nl+1);
122          nl=nl1;
123       }
124    }
125 }
126