aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/xkb/XKBMisc.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/xkb/XKBMisc.c')
-rw-r--r--xorg-server/xkb/XKBMisc.c88
1 files changed, 66 insertions, 22 deletions
diff --git a/xorg-server/xkb/XKBMisc.c b/xorg-server/xkb/XKBMisc.c
index a9d8b17c0..867906046 100644
--- a/xorg-server/xkb/XKBMisc.c
+++ b/xorg-server/xkb/XKBMisc.c
@@ -32,8 +32,6 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <stdio.h>
#include <X11/X.h>
-#define NEED_EVENTS
-#define NEED_REPLIES
#include <X11/Xproto.h>
#include "misc.h"
#include "inputstr.h"
@@ -58,6 +56,7 @@ register int i;
unsigned int empty;
int nSyms[XkbNumKbdGroups];
int nGroups,tmp,groupsWidth;
+BOOL replicated = FALSE;
/* Section 12.2 of the protocol describes this process in more detail */
/* Step 1: find the # of symbols in the core mapping per group */
@@ -91,27 +90,70 @@ int nGroups,tmp,groupsWidth;
for (i=2;i<nSyms[XkbGroup2Index];i++) {
xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,i)]= CORE_SYM(tmp+i);
}
- tmp= nSyms[XkbGroup1Index]+nSyms[XkbGroup2Index];
- if ((tmp>=map_width)&&
- ((protected&(XkbExplicitKeyType3Mask|XkbExplicitKeyType4Mask))==0)) {
+
+ /* Special case: if only the first group is explicit, and the symbols
+ * replicate across all groups, then we have a Section 12.4 replication */
+ if ((protected & ~XkbExplicitKeyType1Mask) == 0)
+ {
+ int j, width = nSyms[XkbGroup1Index];
+
+ replicated = TRUE;
+
+ /* Check ABAB in ABABCDECDEABCDE */
+ if ((width > 0 && CORE_SYM(0) != CORE_SYM(2)) ||
+ (width > 1 && CORE_SYM(1) != CORE_SYM(3)))
+ replicated = FALSE;
+
+ /* Check CDECDE in ABABCDECDEABCDE */
+ for (i = 2; i < width && replicated; i++)
+ {
+ if (CORE_SYM(2 + i) != CORE_SYM(i + width))
+ replicated = FALSE;
+ }
+
+ /* Check ABCDE in ABABCDECDEABCDE */
+ for (j = 2; replicated &&
+ j < XkbNumKbdGroups &&
+ map_width >= width * (j + 1); j++)
+ {
+ for (i = 0; i < width && replicated; i++)
+ {
+ if (CORE_SYM(((i < 2) ? i : 2 + i)) != CORE_SYM(i + width * j))
+ replicated = FALSE;
+ }
+ }
+ }
+
+ if (replicated)
+ {
+ nSyms[XkbGroup2Index]= 0;
nSyms[XkbGroup3Index]= 0;
nSyms[XkbGroup4Index]= 0;
- nGroups= 2;
- }
- else {
- nGroups= 3;
- for (i=0;i<nSyms[XkbGroup3Index];i++,tmp++) {
- xkb_syms_rtrn[XKB_OFFSET(XkbGroup3Index,i)]= CORE_SYM(tmp);
- }
- if ((tmp<map_width)||(protected&XkbExplicitKeyType4Mask)) {
- nGroups= 4;
- for (i=0;i<nSyms[XkbGroup4Index];i++,tmp++) {
- xkb_syms_rtrn[XKB_OFFSET(XkbGroup4Index,i)]= CORE_SYM(tmp);
- }
- }
- else {
- nSyms[XkbGroup4Index]= 0;
- }
+ nGroups= 1;
+ } else
+ {
+ tmp= nSyms[XkbGroup1Index]+nSyms[XkbGroup2Index];
+ if ((tmp>=map_width)&&
+ ((protected&(XkbExplicitKeyType3Mask|XkbExplicitKeyType4Mask))==0)) {
+ nSyms[XkbGroup3Index]= 0;
+ nSyms[XkbGroup4Index]= 0;
+ nGroups= 2;
+ } else
+ {
+ nGroups= 3;
+ for (i=0;i<nSyms[XkbGroup3Index];i++,tmp++) {
+ xkb_syms_rtrn[XKB_OFFSET(XkbGroup3Index,i)]= CORE_SYM(tmp);
+ }
+ if ((tmp<map_width)||(protected&XkbExplicitKeyType4Mask)) {
+ nGroups= 4;
+ for (i=0;i<nSyms[XkbGroup4Index];i++,tmp++) {
+ xkb_syms_rtrn[XKB_OFFSET(XkbGroup4Index,i)]= CORE_SYM(tmp);
+ }
+ }
+ else {
+ nSyms[XkbGroup4Index]= 0;
+ }
+ }
}
/* steps 3&4: alphanumeric expansion, assign canonical types */
empty= 0;
@@ -200,6 +242,8 @@ int nGroups,tmp,groupsWidth;
Bool identical;
for (i=1,identical=True;identical&&(i<nGroups);i++) {
KeySym *syms;
+ if (nSyms[i] != nSyms[XkbGroup1Index])
+ identical = False;
syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)];
for (s=0;identical&&(s<nSyms[i]);s++) {
if (syms[s]!=xkb_syms_rtrn[s])
@@ -463,7 +507,7 @@ unsigned changed,tmp;
mc->changed|= changed;
}
if (interps!=ibuf)
- _XkbFree(interps);
+ xfree(interps);
return True;
}