guacamole-spice-protocol/src/protocols/rdp/decompose.c

178 lines
6.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include "config.h"
#include "keyboard.h"
/**
* The X11 keysym for the dead key which types a grave (`).
*/
#define DEAD_GRAVE 0xFE50
/**
* The X11 keysym for the dead key which types an acute (´). Note that this is
* NOT equivalent to an apostrophe or single quote.
*/
#define DEAD_ACUTE 0xFE51
/**
* The X11 keysym for the dead key which types a circumflex/caret (^).
*/
#define DEAD_CIRCUMFLEX 0xFE52
/**
* The X11 keysym for the dead key which types a tilde (~).
*/
#define DEAD_TILDE 0xFE53
/**
* The X11 keysym for the dead key which types a dieresis/umlaut (¨).
*/
#define DEAD_DIERESIS 0xFE57
/**
* The X11 keysym for the dead key which types an abovering (˚). Note that this
* is NOT equivalent to the degree symbol.
*/
#define DEAD_ABOVERING 0xFE58
/**
* The decomposed form of a key that can be typed using two keypresses: a dead
* key followed by a base key. For example, on a keyboard which lacks a single
* dedicated key for doing the same, "ó" would be typed using the dead acute
* key followed by the "o" key. The dead key and base key are pressed and
* released in sequence; they are not held down.
*/
typedef struct guac_rdp_decomposed_key {
/**
* The keysym of the dead key which must first be pressed and released to
* begin typing the desired character. The dead key defines the diacritic
* which will be applied to the character typed by the base key.
*/
int dead_keysym;
/**
* The keysym of the base key which must be pressed and released to finish
* typing the desired character. The base key defines the normal form of
* the character (the form which lacks any diacritic) to which the
* diacritic defined by the previously-pressed dead key will be applied.
*/
int base_keysym;
} guac_rdp_decomposed_key;
/**
* A lookup table of all known decomposed forms of various keysyms. Keysyms map
* directly to entries within this table. A keysym which has no entry within
* this table does not have a defined decomposed form (or at least does not
* have a decomposed form relevant to RDP).
*/
guac_rdp_decomposed_key guac_rdp_decomposed_keys[256] = {
/* ^ */ [0x005E] = { DEAD_CIRCUMFLEX, ' ' },
/* ` */ [0x0060] = { DEAD_GRAVE, ' ' },
/* ~ */ [0x007E] = { DEAD_TILDE, ' ' },
/* ¨ */ [0x00A8] = { DEAD_DIERESIS, ' ' },
/* ´ */ [0x00B4] = { DEAD_ACUTE, ' ' },
/* À */ [0x00C0] = { DEAD_GRAVE, 'A' },
/* Á */ [0x00C1] = { DEAD_ACUTE, 'A' },
/* Â */ [0x00C2] = { DEAD_CIRCUMFLEX, 'A' },
/* Ã */ [0x00C3] = { DEAD_TILDE, 'A' },
/* Ä */ [0x00C4] = { DEAD_DIERESIS, 'A' },
/* Å */ [0x00C5] = { DEAD_ABOVERING, 'A' },
/* È */ [0x00C8] = { DEAD_GRAVE, 'E' },
/* É */ [0x00C9] = { DEAD_ACUTE, 'E' },
/* Ê */ [0x00CA] = { DEAD_CIRCUMFLEX, 'E' },
/* Ë */ [0x00CB] = { DEAD_DIERESIS, 'E' },
/* Ì */ [0x00CC] = { DEAD_GRAVE, 'I' },
/* Í */ [0x00CD] = { DEAD_ACUTE, 'I' },
/* Î */ [0x00CE] = { DEAD_CIRCUMFLEX, 'I' },
/* Ï */ [0x00CF] = { DEAD_DIERESIS, 'I' },
/* Ñ */ [0x00D1] = { DEAD_TILDE, 'N' },
/* Ò */ [0x00D2] = { DEAD_GRAVE, 'O' },
/* Ó */ [0x00D3] = { DEAD_ACUTE, 'O' },
/* Ô */ [0x00D4] = { DEAD_CIRCUMFLEX, 'O' },
/* Õ */ [0x00D5] = { DEAD_TILDE, 'O' },
/* Ö */ [0x00D6] = { DEAD_DIERESIS, 'O' },
/* Ù */ [0x00D9] = { DEAD_GRAVE, 'U' },
/* Ú */ [0x00DA] = { DEAD_ACUTE, 'U' },
/* Û */ [0x00DB] = { DEAD_CIRCUMFLEX, 'U' },
/* Ü */ [0x00DC] = { DEAD_DIERESIS, 'U' },
/* Ý */ [0x00DD] = { DEAD_ACUTE, 'Y' },
/* à */ [0x00E0] = { DEAD_GRAVE, 'a' },
/* á */ [0x00E1] = { DEAD_ACUTE, 'a' },
/* â */ [0x00E2] = { DEAD_CIRCUMFLEX, 'a' },
/* ã */ [0x00E3] = { DEAD_TILDE, 'a' },
/* ä */ [0x00E4] = { DEAD_DIERESIS, 'a' },
/* å */ [0x00E5] = { DEAD_ABOVERING, 'a' },
/* è */ [0x00E8] = { DEAD_GRAVE, 'e' },
/* é */ [0x00E9] = { DEAD_ACUTE, 'e' },
/* ê */ [0x00EA] = { DEAD_CIRCUMFLEX, 'e' },
/* ë */ [0x00EB] = { DEAD_DIERESIS, 'e' },
/* ì */ [0x00EC] = { DEAD_GRAVE, 'i' },
/* í */ [0x00ED] = { DEAD_ACUTE, 'i' },
/* î */ [0x00EE] = { DEAD_CIRCUMFLEX, 'i' },
/* ï */ [0x00EF] = { DEAD_DIERESIS, 'i' },
/* ñ */ [0x00F1] = { DEAD_TILDE, 'n' },
/* ò */ [0x00F2] = { DEAD_GRAVE, 'o' },
/* ó */ [0x00F3] = { DEAD_ACUTE, 'o' },
/* ô */ [0x00F4] = { DEAD_CIRCUMFLEX, 'o' },
/* õ */ [0x00F5] = { DEAD_TILDE, 'o' },
/* ö */ [0x00F6] = { DEAD_DIERESIS, 'o' },
/* ù */ [0x00F9] = { DEAD_GRAVE, 'u' },
/* ú */ [0x00FA] = { DEAD_ACUTE, 'u' },
/* û */ [0x00FB] = { DEAD_CIRCUMFLEX, 'u' },
/* ü */ [0x00FC] = { DEAD_DIERESIS, 'u' },
/* ý */ [0x00FD] = { DEAD_ACUTE, 'y' },
/* ÿ */ [0x00FF] = { DEAD_DIERESIS, 'y' }
};
int guac_rdp_decompose_keysym(guac_rdp_keyboard* keyboard, int keysym) {
/* Verify keysym is within range of lookup table */
if (keysym < 0x00 || keysym > 0xFF)
return 1;
/* Verify keysym is actually defined within lookup table */
guac_rdp_decomposed_key* key = &guac_rdp_decomposed_keys[keysym];
if (!key->dead_keysym)
return 1;
/* Cannot type using decomposed keys if those keys are not defined within
* the current layout */
if (!guac_rdp_keyboard_is_defined(keyboard, key->dead_keysym)
|| !guac_rdp_keyboard_is_defined(keyboard, key->base_keysym))
return 1;
/* Press dead key */
guac_rdp_keyboard_send_event(keyboard, key->dead_keysym, 1);
guac_rdp_keyboard_send_event(keyboard, key->dead_keysym, 0);
/* Press base key */
guac_rdp_keyboard_send_event(keyboard, key->base_keysym, 1);
guac_rdp_keyboard_send_event(keyboard, key->base_keysym, 0);
/* Decomposed key successfully typed */
return 0;
}