chiark / gitweb /
Merge branch 'stable-5.x' 6.0
authorIan Jackson <ian@liberator.relativity.greenend.org.uk>
Sat, 21 Nov 2009 13:44:21 +0000 (13:44 +0000)
committerIan Jackson <ian@liberator.relativity.greenend.org.uk>
Sat, 21 Nov 2009 13:44:21 +0000 (13:44 +0000)
yarrg/convert.c
yarrg/convert.h
yarrg/pages.c

index ce3ad0b49619f5517e9a5f0384d69535921b0fc0..b7925b806e4f214844f119aa3be9a889d665a92f 100644 (file)
@@ -233,6 +233,7 @@ int main(int argc, char **argv) {
 
   sysassert( setlocale(LC_MESSAGES,"") );
   sysassert( setlocale(LC_CTYPE,"en_GB.UTF-8") ||
+            setlocale(LC_CTYPE,"en_US.UTF-8") ||
             setlocale(LC_CTYPE,"en.UTF-8") );
 
 #define ARGVAL  ((*++argv) ? *argv : \
index 75f61793e8fb9b25434fefd17ce39ef46128998f..a9e6a686d1abda589c359cb92e0ac258bbab2e02 100644 (file)
@@ -31,6 +31,7 @@
 #define DEBUG_FLAG_LIST                                \
    DF(findypp)                                 \
    DF(pages)                                   \
+   DF(keymap)                                  \
    DF(rect)                                    \
    DF(pixmap)                                  \
    DF(struct)                                  \
index 28364a07381d0035b21b5907af7486bc7aaab53f..d5385d3bdd71102cf715a1606cf13a8d62881a66 100644 (file)
@@ -55,23 +55,155 @@ static XImage *shmim;
 static XShmSegmentInfo shminfo;
 
 DEBUG_DEFINE_DEBUGF(pages)
+DEBUG_DEFINE_SOME_DEBUGF(keymap,keydebugf)
 
 #define xassert(what)                                  \
   ((what) ? (void)0 :                                  \
    fatal("X11 operation unexpectedly failed."          \
         " %s:%d: %s\n", __FILE__,__LINE__,#what))
 
-static KeyCode keycode(KeySym sym) {
-  return XKeysymToKeycode(disp,sym);
+
+/*---------- keyboard map ----------*/
+
+#define KEYS(EACH_KEY)                         \
+  EACH_KEY(XK_slash)                           \
+  EACH_KEY(XK_w)                               \
+  EACH_KEY(XK_Return)                          \
+  EACH_KEY(XK_Prior)                           \
+  EACH_KEY(XK_Next)
+
+#define MAXMAPCOL 6
+typedef struct {
+  int len;
+  int kc[3];
+} MappedKey;
+
+#define KEY_MAP_DEF(xk) \
+static MappedKey mk_##xk;
+KEYS(KEY_MAP_DEF)
+
+typedef struct {
+  int isdef; /* 'y' if defined; otherwise char indicating why not */
+  int kc;
+} MappedModifier;
+
+static int kc_min, kc_max;
+static MappedModifier mm_shift, mm_modeswitch, mm_isol3shift;
+static KeySym *mapping;
+static int mapwidth;
+
+static void keymap_lookup_modifier(MappedModifier *mm, const char *what,
+                                  KeySym sym, char ifnot) {
+  int kc;
+  keydebugf("KEYMAP modifier lookup %-10s %#lx or '%c' ", what,
+           (unsigned long)sym, ifnot);
+
+  mm->isdef= ifnot;
+  for (kc=kc_min; kc <= kc_max; kc++) {
+    if (mapping[(kc-kc_min)*mapwidth] == sym) {
+      keydebugf(" found kc=%d\n", kc);
+      mm->isdef= 'y';
+      mm->kc= kc;
+      return;
+    }
+  }
+  keydebugf(" none\n");
 }
 
-void screenshot_startup(void) {
-  progress("starting...");
-  disp= XOpenDisplay(0);
-  if (!disp) fatal("Unable to open X11 display.");
-  sysassert(! gettimeofday(&tv_startup,0) );
+static void keymap_lookup_key(MappedKey *mk, KeySym sym, const char *what) {
+  const MappedModifier *shift, *xshift;
+  int col, kc;
+  char cols[MAXMAPCOL+1];
+
+  memset(cols,'.',MAXMAPCOL);
+  cols[MAXMAPCOL]= 0;
+
+  for (col=0; col<mapwidth && col<MAXMAPCOL; col++) {
+    keydebugf("KEYMAP lookup %-10s %#lx col=%d ",
+             what, (unsigned long)sym, col);
+
+#define CHECK_SHIFT(sh) do{                                    \
+      if ((sh) && (sh)->isdef!='y') {                          \
+       cols[col]= (sh)->isdef;                                 \
+        keydebugf("no-modifier " #sh "'%c'\n", (sh)->isdef);   \
+       continue;                                               \
+      }                                                                \
+    }while(0)
+
+    shift= col & 1 ? &mm_shift : 0;
+    CHECK_SHIFT(shift);
+
+    xshift= col >= 4 ? &mm_isol3shift :
+            col >= 2 ? &mm_modeswitch :
+            0;
+    CHECK_SHIFT(xshift);
+
+    for (kc=kc_min; kc <= kc_max; kc++) {
+      if (mapping[(kc-kc_min)*mapwidth + col] == sym)
+       goto found;
+    }
+    cols[col]= '_';
+    keydebugf("not-found\n");
+  }
+  fprintf(stderr,"\n"
+         "Unable to find a key to press to generate %s.\n"
+         "(Technical details: cols:%s sh:%c:%d modesw:%c:%d isol3:%c:%d)\n",
+         what, cols,
+#define SH_DETAILS(sh) mm_##sh.isdef, mm_##sh.kc
+         SH_DETAILS(shift), SH_DETAILS(modeswitch), SH_DETAILS(isol3shift));
+  fatal("Keymap is unsuitable!");
+
+ found:;
+  int *fill= mk->kc;
+  
+  if (xshift) *fill++ = xshift->kc;
+  if (shift)  *fill++ = shift->kc;
+  *fill++ += kc;
+  mk->len= fill - mk->kc;
+  keydebugf("found kc=%d len=%d\n",kc,mk->len);
 }
 
+static void keymap_startup(void) {
+  xassert( XDisplayKeycodes(disp,&kc_min,&kc_max) );
+  keydebugf("KEYMAP keycodes %d..%d\n",kc_min,kc_max);
+
+  xassert( mapping= XGetKeyboardMapping(disp, kc_min, kc_max-kc_min+1,
+                                       &mapwidth) );
+  keydebugf("KEYMAP got keyboard map\n");
+
+  XModifierKeymap *modmap;
+  xassert( modmap= XGetModifierMapping(disp) );
+  keydebugf("KEYMAP got modifier map\n");
+
+  /* find a shift keycode */
+  mm_shift.isdef= 'x';
+  int modent;
+  for (modent=0; modent<modmap->max_keypermod; modent++) {
+    int kc= modmap->modifiermap[modent];
+    keydebugf("KEYMAP modifier #0 key #%d is %d ", modent, kc);
+    if (!kc) { keydebugf("none\n"); continue; }
+    keydebugf("ok\n");
+    mm_shift.kc= kc;
+    mm_shift.isdef= 'y';
+    break;
+  }
+
+  XFreeModifiermap(modmap);
+
+  /* find keycodes for mode_switch (column+=2) and ISO L3 shift (column+=4) */
+  keymap_lookup_modifier(&mm_modeswitch,"modeswitch", XK_Mode_switch,     'm');
+  keymap_lookup_modifier(&mm_isol3shift,"isol3shift", XK_ISO_Level3_Shift,'l');
+  
+#define KEY_MAP_LOOKUP(xk) \
+  keymap_lookup_key(&mk_##xk, xk, #xk);
+  KEYS(KEY_MAP_LOOKUP)
+
+  XFree(mapping);
+  mapping= 0;
+}
+
+#define SEND_KEY(xk) (send_key(&mk_##xk))
+
 /*---------- pager ----------*/
 
 typedef RgbImage Snapshot;
@@ -176,10 +308,12 @@ static void check_pointer_not_disturbed(void) {
   }
 }
 
-static void send_key(KeySym sym) {
+static void send_key(MappedKey *mk) {
+  int i;
   check_not_disturbed();
-  XTestFakeKeyEvent(disp, keycode(sym),1, 0);
-  XTestFakeKeyEvent(disp, keycode(sym),0, 0);
+  keydebugf("KEYMAP SEND_KEY len=%d kc=%d\n", mk->len, mk->kc[mk->len-1]);
+  for (i=0; i<mk->len; i++) XTestFakeKeyEvent(disp, mk->kc[i], 1, 0);
+  for (i=mk->len; --i>=0; ) XTestFakeKeyEvent(disp, mk->kc[i], 0, 0);
 }
 static void send_mouse_1_updown_here(void) {
   check_not_disturbed();
@@ -207,7 +341,7 @@ static int pgupdown;
 static void send_pgup_many(void) {
   int i;
   for (i=0; i<25; i++) {
-    send_key(XK_Prior);
+    SEND_KEY(XK_Prior);
     pgupdown--;
   }
   debugf("PAGING   PageUp x %d\n",i);
@@ -216,7 +350,7 @@ static void send_pgup_many(void) {
 static void send_pgdown_torestore(void) {
   debugf("PAGING   PageDown x %d\n", -pgupdown);
   while (pgupdown < 0) {
-    send_key(XK_Next);
+    SEND_KEY(XK_Next);
     pgupdown++;
   }
   sync_after_input();
@@ -589,9 +723,9 @@ static void prepare_ypp_client(void) {
   send_mouse_1_updown_here();
   sync_after_input();
   check_not_disturbed();
-  send_key(XK_slash);
-  send_key(XK_w);
-  send_key(XK_Return);
+  SEND_KEY(XK_slash);
+  SEND_KEY(XK_w);
+  SEND_KEY(XK_Return);
   sync_after_input();
 
   Snapshot *status=0;
@@ -793,3 +927,12 @@ void find_yppclient_window(void) {
          " Use --window-id and/or report this as a fault.\n",
          o_ocean || o_pirate ? "matching ": "");
 }
+
+void screenshot_startup(void) {
+  progress("starting...");
+  disp= XOpenDisplay(0);
+  if (!disp) fatal("Unable to open X11 display.");
+  sysassert(! gettimeofday(&tv_startup,0) );
+
+  keymap_startup();
+}