Make bounds of automatic array constant.
[sgt/putty] / minibidi.c
index c13276d..6219366 100644 (file)
 #define OISL   0x80    /* Override is L */
 #define OISR   0x40    /* Override is R */
 
+/* For standalone compilation in a testing mode.
+ * Still depends on the PuTTY headers for snewn and sfree, but can avoid
+ * _linking_ with any other PuTTY code. */
+#ifdef TEST_GETTYPE
+#define safemalloc malloc
+#define safefree free
+#endif
+
 /* Shaping Helpers */
 #define STYPE(xh) ((((xh) >= SHAPE_FIRST) && ((xh) <= SHAPE_LAST)) ? \
 shapetypes[(xh)-SHAPE_FIRST].type : SU) /*))*/
@@ -84,7 +92,7 @@ enum {
     B,
     S,
     WS,
-    ON,
+    ON
 };
 
 /* Shaping Types */
@@ -148,7 +156,7 @@ const shape_node shapetypes[] = {
     /* 647 */ {SD, 0xFEE9},
     /* 648 */ {SR, 0xFEED},
     /* 649 */ {SR, 0xFEEF}, /* SD */
-    /* 64A */ {SD, 0xFEF1},
+    /* 64A */ {SD, 0xFEF1}
 };
 
 /*
@@ -840,7 +848,7 @@ unsigned char getType(int ch)
         {0xe0020, 0xe007f, BN},
         {0xe0100, 0xe01ef, NSM},
         {0xf0000, 0xffffd, L},
-        {0x100000, 0x10fffd, L},
+        {0x100000, 0x10fffd, L}
     };
 
     int i, j, k;
@@ -848,7 +856,7 @@ unsigned char getType(int ch)
     i = -1;
     j = lenof(lookup);
 
-    while (j - i > 2) {
+    while (j - i > 1) {
        k = (i + j) / 2;
        if (ch < lookup[k].first)
            j = k;
@@ -870,6 +878,40 @@ unsigned char getType(int ch)
 }
 
 /*
+ * Function exported to front ends to allow them to identify
+ * bidi-active characters (in case, for example, the platform's
+ * text display function can't conveniently be prevented from doing
+ * its own bidi and so special treatment is required for characters
+ * that would cause the bidi algorithm to activate).
+ * 
+ * This function is passed a single Unicode code point, and returns
+ * nonzero if the presence of this code point can possibly cause
+ * the bidi algorithm to do any reordering. Thus, any string
+ * composed entirely of characters for which is_rtl() returns zero
+ * should be safe to pass to a bidi-active platform display
+ * function without fear.
+ * 
+ * (is_rtl() must therefore also return true for any character
+ * which would be affected by Arabic shaping, but this isn't
+ * important because all such characters are right-to-left so it
+ * would have flagged them anyway.)
+ */
+int is_rtl(int c)
+{
+    /*
+     * After careful reading of the Unicode bidi algorithm (URL as
+     * given at the top of this file) I believe that the only
+     * character classes which can possibly cause trouble are R,
+     * AL, RLE and RLO. I think that any string containing no
+     * character in any of those classes will be displayed
+     * uniformly left-to-right by the Unicode bidi algorithm.
+     */
+    const int mask = (1<<R) | (1<<AL) | (1<<RLE) | (1<<RLO);
+
+    return mask & (1 << (getType(c)));
+}
+
+/*
  * The most significant 2 bits of each level are used to store
  * Override status of each character
  * This function sets the override bits of level according
@@ -1810,3 +1852,47 @@ void doMirror(wchar_t* ch)
        }
     }
 }
+
+#ifdef TEST_GETTYPE
+
+#include <stdio.h>
+#include <assert.h>
+
+int main(int argc, char **argv)
+{
+    static const struct { int type; char *name; } typetoname[] = {
+#define TYPETONAME(X) { X , #X }
+       TYPETONAME(L),
+       TYPETONAME(LRE),
+       TYPETONAME(LRO),
+       TYPETONAME(R),
+       TYPETONAME(AL),
+       TYPETONAME(RLE),
+       TYPETONAME(RLO),
+       TYPETONAME(PDF),
+       TYPETONAME(EN),
+       TYPETONAME(ES),
+       TYPETONAME(ET),
+       TYPETONAME(AN),
+       TYPETONAME(CS),
+       TYPETONAME(NSM),
+       TYPETONAME(BN),
+       TYPETONAME(B),
+       TYPETONAME(S),
+       TYPETONAME(WS),
+       TYPETONAME(ON),
+#undef TYPETONAME
+    };
+    int i;
+
+    for (i = 1; i < argc; i++) {
+       unsigned long chr = strtoul(argv[i], NULL, 0);
+       int type = getType(chr);
+       assert(typetoname[type].type == type);
+       printf("U+%04x: %s\n", chr, typetoname[type].name);
+    }
+
+    return 0;
+}
+
+#endif