예제 #1
0
const char *
gui_mouse_event_code2key (const char *code)
{
    int i, x, y, code_utf8, length;
    double diff_x, diff_y, distance, angle, pi4;
    static char key[128];
    const char *ptr_code;

    key[0] = '\0';

    /*
     * mouse code must have at least:
     *   one code (for event) + X + Y == 3 bytes or 3 UTF-8 chars
     */
    code_utf8 = utf8_is_valid (code, NULL);
    length = (code_utf8) ? utf8_strlen (code) : (int)strlen (code);
    if (length < 3)
        return NULL;

    /* get coordinates and button */
    if (code_utf8)
    {
        /* get coordinates using UTF-8 chars in code */
        x = utf8_char_int (code + 1) - 33;
        ptr_code = utf8_next_char (code + 1);
        if (!ptr_code)
            return NULL;
        y = utf8_char_int (ptr_code) - 33;
    }
    else
    {
        /* get coordinates using ISO chars in code */
        x = ((unsigned char)code[1]) - 33;
        y = ((unsigned char)code[2]) - 33;
    }
    if (x < 0)
        x = 0;
    if (y < 0)
        y = 0;

    /* ignore code if it's motion/end code received as first event */
    if ((gui_mouse_event_index == 0)
        && (MOUSE_CODE_MOTION(code[0]) || MOUSE_CODE_END(code[0])))
    {
        return NULL;
    }

    /* set data in "gui_mouse_event_xxx" */
    gui_mouse_event_x[gui_mouse_event_index] = x;
    gui_mouse_event_y[gui_mouse_event_index] = y;
    if (gui_mouse_event_index == 0)
        gui_mouse_event_button = code[0];

    if (gui_mouse_event_index == 0)
        gui_mouse_event_index = 1;

    /*
     * browse wheel codes, if one code is found, return event name immediately
     */
    for (i = 0; gui_mouse_wheel_codes[i][0]; i++)
    {
        if (code[0] == gui_mouse_wheel_codes[i][0][0])
        {
            strcat (key, gui_mouse_wheel_codes[i][1]);
            gui_mouse_event_x[1] = gui_mouse_event_x[0];
            gui_mouse_event_y[1] = gui_mouse_event_y[0];
            return key;
        }
    }

    /* add name of button event */
    for (i = 0; gui_mouse_button_codes[i][0]; i++)
    {
        if (gui_mouse_event_button == gui_mouse_button_codes[i][0][0])
        {
            strcat (key, gui_mouse_button_codes[i][1]);
            break;
        }
    }

    /* nothing found, reset now or mouse will be stuck */
    if (!key[0])
    {
        gui_mouse_event_reset ();
        return NULL;
    }

    if (!MOUSE_CODE_END(code[0]))
    {
        strcat (key, "-event-");
        if (MOUSE_CODE_MOTION(code[0])) {
            strcat (key, "drag");
        }
        else
        {
            gui_mouse_event_x[1] = gui_mouse_event_x[0];
            gui_mouse_event_y[1] = gui_mouse_event_y[0];
            strcat (key, "down");
        }
        return key;
    }

    /*
     * Mouse gesture: if (x,y) on release is different from (x,y) on click,
     * compute distance and angle between 2 points.
     *
     * Distance: sqrt((x2-x1)²+(y2-y1)²)
     * Angle   : atan2(x1-x1, y2-y1)
     *
     * Angle:
     *
     *              3.14             pi
     *               /\
     *       -2.35   ||   2.35       3/4 * pi
     *               ||
     *   -1.57  /----++----\  1.57   1/2 * pi
     *          \----++----/
     *               ||
     *       -0.78   ||   0.78       1/4 * pi
     *               \/
     *              0.00             0
     *
     * Possible returned gestures are:
     *
     *   key name                   | dist. | angle
     *   ---------------------------+-------+--------------------------
     *   buttonX-gesture-up         | 3..19 | -2.35..-3.14 + 2.35..3.14
     *   buttonX-gesture-up-long    | >= 20 |
     *   buttonX-gesture-down       | 3..19 | -0.78..0.78
     *   buttonX-gesture-down-long  | >= 20 |
     *   buttonX-gesture-left       | 3..39 | -0.78..-2.35
     *   buttonX-gesture-left-long  | >= 40 |
     *   buttonX-gesture-right      | 3..39 |  0.78..2.35
     *   buttonX-gesture-right-long | >= 40 |
     */

    if (key[0]
        && ((gui_mouse_event_x[0] != gui_mouse_event_x[1])
            || (gui_mouse_event_y[0] != gui_mouse_event_y[1])))
    {
        diff_x = gui_mouse_event_x[1] - gui_mouse_event_x[0];
        diff_y = gui_mouse_event_y[1] - gui_mouse_event_y[0];
        distance = sqrt ((diff_x * diff_x) + (diff_y * diff_y));
        if (distance >= 3)
        {
            angle = atan2 ((double)(gui_mouse_event_x[1] - gui_mouse_event_x[0]),
                           (double)(gui_mouse_event_y[1] - gui_mouse_event_y[0]));
            pi4 = 3.14159265358979 / 4;
            if ((angle <= pi4 * (-3)) || (angle >= pi4 * 3))
            {
                strcat (key, "-gesture-up");
                if (distance >= 20)
                    strcat (key, "-long");
            }
            else if ((angle >= pi4 * (-1)) && (angle <= pi4))
            {
                strcat (key, "-gesture-down");
                if (distance >= 20)
                    strcat (key, "-long");
            }
            else if ((angle >= pi4 * (-3)) && (angle <= pi4 * (-1)))
            {
                strcat (key, "-gesture-left");
                if (distance >= 40)
                    strcat (key, "-long");
            }
            else if ((angle >= pi4) && (angle <= pi4 * 3))
            {
                strcat (key, "-gesture-right");
                if (distance >= 40)
                    strcat (key, "-long");
            }
        }
    }

    return key;
}
예제 #2
0
TEST(Utf8, Convert)
{
    char result[5];

    /* get UTF-8 char as integer */
    BYTES_EQUAL(0, utf8_char_int (NULL));
    BYTES_EQUAL(0, utf8_char_int (""));
    BYTES_EQUAL(65, utf8_char_int ("ABC"));
    BYTES_EQUAL(235, utf8_char_int ("ë"));
    BYTES_EQUAL(0x20ac, utf8_char_int ("€"));
    BYTES_EQUAL(0x24b62, utf8_char_int (han_char));

    BYTES_EQUAL(0x0, utf8_char_int ("\xc0\x80"));   /* invalid */
    BYTES_EQUAL(0x7f, utf8_char_int ("\xc1\xbf"));  /* invalid */
    BYTES_EQUAL(0x80, utf8_char_int ("\xc2\x80"));
    BYTES_EQUAL(0x7ff, utf8_char_int ("\xdf\xbf"));

    BYTES_EQUAL(0x0, utf8_char_int ("\xe0\x80\x80"));     /* invalid */
    BYTES_EQUAL(0x7ff, utf8_char_int ("\xe0\x9f\xbf"));   /* invalid */
    LONGS_EQUAL(0xd800, utf8_char_int ("\xed\xa0\x80"));  /* invalid */
    LONGS_EQUAL(0xdfff, utf8_char_int ("\xed\xbf\xbf"));  /* invalid */
    BYTES_EQUAL(0x800, utf8_char_int ("\xe0\xa0\x80"));
    BYTES_EQUAL(0xd7ff, utf8_char_int ("\xed\x9f\xbf"));
    BYTES_EQUAL(0xe000, utf8_char_int ("\xe7\x80\x80"));
    BYTES_EQUAL(0xffff, utf8_char_int ("\xef\xbf\xbf"));

    BYTES_EQUAL(0x0, utf8_char_int ("\xf0\x80\x80\x80"));     /* invalid */
    BYTES_EQUAL(0xffff, utf8_char_int ("\xf0\x8f\xbf\xbf"));  /* invalid */
    BYTES_EQUAL(0x10000, utf8_char_int ("\xf0\x90\x80\x80"));
    BYTES_EQUAL(0x1fffff, utf8_char_int ("\xf7\xbf\xbf\xbf"));

    /* convert unicode char to a string */
    utf8_int_string (0, NULL);
    utf8_int_string (0, result);
    STRCMP_EQUAL("", result);
    utf8_int_string (235, result);
    STRCMP_EQUAL("ë", result);
    utf8_int_string (0x20ac, result);
    STRCMP_EQUAL("€", result);
    utf8_int_string (0x24b62, result);
    STRCMP_EQUAL(han_char, result);

    /* get wide char */
    BYTES_EQUAL(WEOF, utf8_wide_char (NULL));
    BYTES_EQUAL(WEOF, utf8_wide_char (""));
    BYTES_EQUAL(65, utf8_wide_char ("A"));
    BYTES_EQUAL(0xc3ab, utf8_wide_char ("ë"));
    BYTES_EQUAL(0xe282ac, utf8_wide_char ("€"));
    BYTES_EQUAL(0xf0a4ada2, utf8_wide_char (han_char));
}
예제 #3
0
파일: wee-utf8.c 프로젝트: emning/weechat
int
utf8_is_valid (const char *string, char **error)
{
    int code_point;

    while (string && string[0])
    {
        /*
         * UTF-8, 2 bytes, should be: 110vvvvv 10vvvvvv
         * and in range: U+0080 - U+07FF
         */
        if (((unsigned char)(string[0]) & 0xE0) == 0xC0)
        {
            if (!string[1] || (((unsigned char)(string[1]) & 0xC0) != 0x80))
                goto invalid;
            code_point = utf8_char_int (string);
            if ((code_point < 0x0080) || (code_point > 0x07FF))
                goto invalid;
            string += 2;
        }
        /*
         * UTF-8, 3 bytes, should be: 1110vvvv 10vvvvvv 10vvvvvv
         * and in range: U+0800 - U+FFFF
         * (note: high and low surrogate halves used by UTF-16 (U+D800 through
         * U+DFFF) are not legal Unicode values)
         */
        else if (((unsigned char)(string[0]) & 0xF0) == 0xE0)
        {
            if (!string[1] || !string[2]
                || (((unsigned char)(string[1]) & 0xC0) != 0x80)
                || (((unsigned char)(string[2]) & 0xC0) != 0x80))
            {
                goto invalid;
            }
            code_point = utf8_char_int (string);
            if ((code_point < 0x0800)
                || (code_point > 0xFFFF)
                || ((code_point >= 0xD800) && (code_point <= 0xDFFF)))
            {
                goto invalid;
            }
            string += 3;
        }
        /*
         * UTF-8, 4 bytes, should be: 11110vvv 10vvvvvv 10vvvvvv 10vvvvvv
         * and in range: U+10000 - U+1FFFFF
         */
        else if (((unsigned char)(string[0]) & 0xF8) == 0xF0)
        {
            if (!string[1] || !string[2] || !string[3]
                || (((unsigned char)(string[1]) & 0xC0) != 0x80)
                || (((unsigned char)(string[2]) & 0xC0) != 0x80)
                || (((unsigned char)(string[3]) & 0xC0) != 0x80))
            {
                goto invalid;
            }
            code_point = utf8_char_int(string);
            if ((code_point < 0x10000) || (code_point > 0x1FFFFF))
                goto invalid;
            string += 4;
        }
        /* UTF-8, 1 byte, should be: 0vvvvvvv */
        else if ((unsigned char)(string[0]) >= 0x80)
            goto invalid;
        else
            string++;
    }
    if (error)
        *error = NULL;
    return 1;

invalid:
    if (error)
        *error = (char *)string;
    return 0;
}