From 85a310d3f53b71be9a5e0604cba9d899df1ba20f Mon Sep 17 00:00:00 2001 From: shin jaejong Date: Wed, 21 Sep 2022 12:06:14 +0900 Subject: [PATCH] integrate libvncserver, connection checked --- rfb/default8x16.h | 266 ++++++++ rfb/keysym.h | 1638 +++++++++++++++++++++++++++++++++++++++++++++++ rfb/rfb.h | 1297 +++++++++++++++++++++++++++++++++++++ rfb/rfbclient.h | 833 ++++++++++++++++++++++++ rfb/rfbconfig.h | 201 ++++++ rfb/rfbconfig.h.cmakein | 201 ++++++ rfb/rfbproto.h | 1556 ++++++++++++++++++++++++++++++++++++++++++++ rfb/rfbregion.h | 65 ++ rfb/threading.h | 95 +++ vncserver.c | 84 +++ weston-vncserver | Bin 161272 -> 165920 bytes 11 files changed, 6236 insertions(+) create mode 100644 rfb/default8x16.h create mode 100644 rfb/keysym.h create mode 100644 rfb/rfb.h create mode 100644 rfb/rfbclient.h create mode 100644 rfb/rfbconfig.h create mode 100644 rfb/rfbconfig.h.cmakein create mode 100644 rfb/rfbproto.h create mode 100644 rfb/rfbregion.h create mode 100644 rfb/threading.h diff --git a/rfb/default8x16.h b/rfb/default8x16.h new file mode 100644 index 0000000..6096b1c --- /dev/null +++ b/rfb/default8x16.h @@ -0,0 +1,266 @@ +#ifndef _DEFAULT_8_X_16_H +#define _DEFAULT_8_X_16_H + +static unsigned char default8x16FontData[4096+1]={ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x7e,0xff,0xdb,0xff,0xff,0xc3,0xe7,0xff,0xff,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x6c,0xfe,0xfe,0xfe,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x38,0x7c,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x18,0x3c,0x3c,0xe7,0xe7,0xe7,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x18,0x3c,0x7e,0xff,0xff,0x7e,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00,0x00,0x00, +0xff,0xff,0xff,0xff,0xff,0xff,0xe7,0xc3,0xc3,0xe7,0xff,0xff,0xff,0xff,0xff,0xff, +0x00,0x00,0x00,0x00,0x00,0x3c,0x66,0x42,0x42,0x66,0x3c,0x00,0x00,0x00,0x00,0x00, +0xff,0xff,0xff,0xff,0xff,0xc3,0x99,0xbd,0xbd,0x99,0xc3,0xff,0xff,0xff,0xff,0xff, +0x00,0x00,0x1e,0x0e,0x1a,0x32,0x78,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x66,0x66,0x66,0x66,0x3c,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x3f,0x33,0x3f,0x30,0x30,0x30,0x30,0x70,0xf0,0xe0,0x00,0x00,0x00,0x00, +0x00,0x00,0x7f,0x63,0x7f,0x63,0x63,0x63,0x63,0x67,0xe7,0xe6,0xc0,0x00,0x00,0x00, +0x00,0x00,0x00,0x18,0x18,0xdb,0x3c,0xe7,0x3c,0xdb,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfe,0xf8,0xf0,0xe0,0xc0,0x80,0x00,0x00,0x00,0x00, +0x00,0x02,0x06,0x0e,0x1e,0x3e,0xfe,0x3e,0x1e,0x0e,0x06,0x02,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00, +0x00,0x00,0x7f,0xdb,0xdb,0xdb,0x7b,0x1b,0x1b,0x1b,0x1b,0x1b,0x00,0x00,0x00,0x00, +0x00,0x7c,0xc6,0x60,0x38,0x6c,0xc6,0xc6,0x6c,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xfe,0xfe,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x18,0x0c,0xfe,0x0c,0x18,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xfe,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xfe,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x24,0x66,0xff,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7c,0x7c,0xfe,0xfe,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0xfe,0xfe,0x7c,0x7c,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x3c,0x3c,0x3c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x6c,0x6c,0xfe,0x6c,0x6c,0x6c,0xfe,0x6c,0x6c,0x00,0x00,0x00,0x00, +0x18,0x18,0x7c,0xc6,0xc2,0xc0,0x7c,0x06,0x06,0x86,0xc6,0x7c,0x18,0x18,0x00,0x00, +0x00,0x00,0x00,0x00,0xc2,0xc6,0x0c,0x18,0x30,0x60,0xc6,0x86,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x6c,0x6c,0x38,0x76,0xdc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x0c,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0c,0x00,0x00,0x00,0x00, +0x00,0x00,0x30,0x18,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x18,0x30,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x02,0x06,0x0c,0x18,0x30,0x60,0xc0,0x80,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xce,0xde,0xf6,0xe6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0x06,0x0c,0x18,0x30,0x60,0xc0,0xc6,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0x06,0x06,0x3c,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x0c,0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xfc,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x60,0xc0,0xc0,0xfc,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0xc6,0x06,0x06,0x0c,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7c,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7e,0x06,0x06,0x06,0x0c,0x78,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x06,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x06,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x60,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x60,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0x0c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xde,0xde,0xde,0xdc,0xc0,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x66,0x66,0x66,0x66,0xfc,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0xf8,0x6c,0x66,0x66,0x66,0x66,0x66,0x66,0x6c,0xf8,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xde,0xc6,0xc6,0x66,0x3a,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00, +0x00,0x00,0xe6,0x66,0x66,0x6c,0x78,0x78,0x6c,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0xf0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xe7,0xff,0xff,0xdb,0xc3,0xc3,0xc3,0xc3,0xc3,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xd6,0xde,0x7c,0x0c,0x0e,0x00,0x00, +0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x6c,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0x60,0x38,0x0c,0x06,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xff,0xdb,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xdb,0xdb,0xff,0x66,0x66,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xc3,0x66,0x3c,0x18,0x18,0x3c,0x66,0xc3,0xc3,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0xff,0xc3,0x86,0x0c,0x18,0x30,0x60,0xc1,0xc3,0xff,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x80,0xc0,0xe0,0x70,0x38,0x1c,0x0e,0x06,0x02,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00,0x00,0x00,0x00, +0x10,0x38,0x6c,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00, +0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0xe0,0x60,0x60,0x78,0x6c,0x66,0x66,0x66,0x66,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc0,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x1c,0x0c,0x0c,0x3c,0x6c,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0xcc,0x78,0x00, +0x00,0x00,0xe0,0x60,0x60,0x6c,0x76,0x66,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x06,0x06,0x00,0x0e,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3c,0x00, +0x00,0x00,0xe0,0x60,0x60,0x66,0x6c,0x78,0x78,0x6c,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xe6,0xff,0xdb,0xdb,0xdb,0xdb,0xdb,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xf0,0x00, +0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x1e,0x00, +0x00,0x00,0x00,0x00,0x00,0xdc,0x76,0x66,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0x60,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x10,0x30,0x30,0xfc,0x30,0x30,0x30,0x30,0x36,0x1c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc3,0xc3,0xc3,0xdb,0xdb,0xff,0x66,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc3,0x66,0x3c,0x18,0x3c,0x66,0xc3,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0xf8,0x00, +0x00,0x00,0x00,0x00,0x00,0xfe,0xcc,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x0e,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0e,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x70,0x18,0x18,0x18,0x0e,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00, +0x00,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xc6,0xfe,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x0c,0x06,0x7c,0x00,0x00, +0x00,0x00,0xcc,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x0c,0x18,0x30,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x10,0x38,0x6c,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0xcc,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x38,0x6c,0x38,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x3c,0x66,0x60,0x60,0x66,0x3c,0x0c,0x06,0x3c,0x00,0x00,0x00, +0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x18,0x3c,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0xc6,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x38,0x6c,0x38,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x18,0x30,0x60,0x00,0xfe,0x66,0x60,0x7c,0x60,0x60,0x66,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x6e,0x3b,0x1b,0x7e,0xd8,0xdc,0x77,0x00,0x00,0x00,0x00, +0x00,0x00,0x3e,0x6c,0xcc,0xcc,0xfe,0xcc,0xcc,0xcc,0xcc,0xce,0x00,0x00,0x00,0x00, +0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x30,0x78,0xcc,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0x78,0x00, +0x00,0xc6,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0xc6,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x18,0x18,0x7e,0xc3,0xc0,0xc0,0xc0,0xc3,0x7e,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xe6,0xfc,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0x66,0x3c,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0xfc,0x66,0x66,0x7c,0x62,0x66,0x6f,0x66,0x66,0x66,0xf3,0x00,0x00,0x00,0x00, +0x00,0x0e,0x1b,0x18,0x18,0x18,0x7e,0x18,0x18,0x18,0x18,0x18,0xd8,0x70,0x00,0x00, +0x00,0x18,0x30,0x60,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x0c,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x18,0x30,0x60,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x18,0x30,0x60,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x76,0xdc,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, +0x76,0xdc,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x3c,0x6c,0x6c,0x3e,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x38,0x6c,0x6c,0x38,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xc0,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00, +0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x60,0xce,0x9b,0x06,0x0c,0x1f,0x00,0x00, +0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x66,0xce,0x96,0x3e,0x06,0x06,0x00,0x00, +0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3c,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x36,0x6c,0xd8,0x6c,0x36,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xd8,0x6c,0x36,0x6c,0xd8,0x00,0x00,0x00,0x00,0x00,0x00, +0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44, +0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa, +0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x3f,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x18,0x18,0x18,0x18,0x18,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x18,0x18,0x18,0x18,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, +0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0xd8,0xd8,0xd8,0xdc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x78,0xcc,0xcc,0xcc,0xd8,0xcc,0xc6,0xc6,0xc6,0xcc,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0xc6,0xc6,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0xfe,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0xfe,0xc6,0x60,0x30,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7e,0xd8,0xd8,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xc0,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x76,0xdc,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x7e,0x18,0x3c,0x66,0x66,0x66,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0x6c,0x38,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x6c,0xc6,0xc6,0xc6,0x6c,0x6c,0x6c,0x6c,0xee,0x00,0x00,0x00,0x00, +0x00,0x00,0x1e,0x30,0x18,0x0c,0x3e,0x66,0x66,0x66,0x66,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7e,0xdb,0xdb,0xdb,0x7e,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x03,0x06,0x7e,0xdb,0xdb,0xf3,0x7e,0x60,0xc0,0x00,0x00,0x00,0x00, +0x00,0x00,0x1c,0x30,0x60,0x60,0x7c,0x60,0x60,0x60,0x30,0x1c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0xff,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x00,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x00,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x0e,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7e,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x38,0x6c,0x6c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0xec,0x6c,0x6c,0x3c,0x1c,0x00,0x00,0x00,0x00, +0x00,0xd8,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x70,0xd8,0x30,0x60,0xc8,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +}; +static int default8x16FontMetaData[256*5+1]={ +0,8,16,0,0,16,8,16,0,0,32,8,16,0,0,48,8,16,0,0,64,8,16,0,0,80,8,16,0,0,96,8,16,0,0,112,8,16,0,0,128,8,16,0,0,144,8,16,0,0,160,8,16,0,0,176,8,16,0,0,192,8,16,0,0,208,8,16,0,0,224,8,16,0,0,240,8,16,0,0,256,8,16,0,0,272,8,16,0,0,288,8,16,0,0,304,8,16,0,0,320,8,16,0,0,336,8,16,0,0,352,8,16,0,0,368,8,16,0,0,384,8,16,0,0,400,8,16,0,0,416,8,16,0,0,432,8,16,0,0,448,8,16,0,0,464,8,16,0,0,480,8,16,0,0,496,8,16,0,0,512,8,16,0,0,528,8,16,0,0,544,8,16,0,0,560,8,16,0,0,576,8,16,0,0,592,8,16,0,0,608,8,16,0,0,624,8,16,0,0,640,8,16,0,0,656,8,16,0,0,672,8,16,0,0,688,8,16,0,0,704,8,16,0,0,720,8,16,0,0,736,8,16,0,0,752,8,16,0,0,768,8,16,0,0,784,8,16,0,0,800,8,16,0,0,816,8,16,0,0,832,8,16,0,0,848,8,16,0,0,864,8,16,0,0,880,8,16,0,0,896,8,16,0,0,912,8,16,0,0,928,8,16,0,0,944,8,16,0,0,960,8,16,0,0,976,8,16,0,0,992,8,16,0,0,1008,8,16,0,0,1024,8,16,0,0,1040,8,16,0,0,1056,8,16,0,0,1072,8,16,0,0,1088,8,16,0,0,1104,8,16,0,0,1120,8,16,0,0,1136,8,16,0,0,1152,8,16,0,0,1168,8,16,0,0,1184,8,16,0,0,1200,8,16,0,0,1216,8,16,0,0,1232,8,16,0,0,1248,8,16,0,0,1264,8,16,0,0,1280,8,16,0,0,1296,8,16,0,0,1312,8,16,0,0,1328,8,16,0,0,1344,8,16,0,0,1360,8,16,0,0,1376,8,16,0,0,1392,8,16,0,0,1408,8,16,0,0,1424,8,16,0,0,1440,8,16,0,0,1456,8,16,0,0,1472,8,16,0,0,1488,8,16,0,0,1504,8,16,0,0,1520,8,16,0,0,1536,8,16,0,0,1552,8,16,0,0,1568,8,16,0,0,1584,8,16,0,0,1600,8,16,0,0,1616,8,16,0,0,1632,8,16,0,0,1648,8,16,0,0,1664,8,16,0,0,1680,8,16,0,0,1696,8,16,0,0,1712,8,16,0,0,1728,8,16,0,0,1744,8,16,0,0,1760,8,16,0,0,1776,8,16,0,0,1792,8,16,0,0,1808,8,16,0,0,1824,8,16,0,0,1840,8,16,0,0,1856,8,16,0,0,1872,8,16,0,0,1888,8,16,0,0,1904,8,16,0,0,1920,8,16,0,0,1936,8,16,0,0,1952,8,16,0,0,1968,8,16,0,0,1984,8,16,0,0,2000,8,16,0,0,2016,8,16,0,0,2032,8,16,0,0,2048,8,16,0,0,2064,8,16,0,0,2080,8,16,0,0,2096,8,16,0,0,2112,8,16,0,0,2128,8,16,0,0,2144,8,16,0,0,2160,8,16,0,0,2176,8,16,0,0,2192,8,16,0,0,2208,8,16,0,0,2224,8,16,0,0,2240,8,16,0,0,2256,8,16,0,0,2272,8,16,0,0,2288,8,16,0,0,2304,8,16,0,0,2320,8,16,0,0,2336,8,16,0,0,2352,8,16,0,0,2368,8,16,0,0,2384,8,16,0,0,2400,8,16,0,0,2416,8,16,0,0,2432,8,16,0,0,2448,8,16,0,0,2464,8,16,0,0,2480,8,16,0,0,2496,8,16,0,0,2512,8,16,0,0,2528,8,16,0,0,2544,8,16,0,0,2560,8,16,0,0,2576,8,16,0,0,2592,8,16,0,0,2608,8,16,0,0,2624,8,16,0,0,2640,8,16,0,0,2656,8,16,0,0,2672,8,16,0,0,2688,8,16,0,0,2704,8,16,0,0,2720,8,16,0,0,2736,8,16,0,0,2752,8,16,0,0,2768,8,16,0,0,2784,8,16,0,0,2800,8,16,0,0,2816,8,16,0,0,2832,8,16,0,0,2848,8,16,0,0,2864,8,16,0,0,2880,8,16,0,0,2896,8,16,0,0,2912,8,16,0,0,2928,8,16,0,0,2944,8,16,0,0,2960,8,16,0,0,2976,8,16,0,0,2992,8,16,0,0,3008,8,16,0,0,3024,8,16,0,0,3040,8,16,0,0,3056,8,16,0,0,3072,8,16,0,0,3088,8,16,0,0,3104,8,16,0,0,3120,8,16,0,0,3136,8,16,0,0,3152,8,16,0,0,3168,8,16,0,0,3184,8,16,0,0,3200,8,16,0,0,3216,8,16,0,0,3232,8,16,0,0,3248,8,16,0,0,3264,8,16,0,0,3280,8,16,0,0,3296,8,16,0,0,3312,8,16,0,0,3328,8,16,0,0,3344,8,16,0,0,3360,8,16,0,0,3376,8,16,0,0,3392,8,16,0,0,3408,8,16,0,0,3424,8,16,0,0,3440,8,16,0,0,3456,8,16,0,0,3472,8,16,0,0,3488,8,16,0,0,3504,8,16,0,0,3520,8,16,0,0,3536,8,16,0,0,3552,8,16,0,0,3568,8,16,0,0,3584,8,16,0,0,3600,8,16,0,0,3616,8,16,0,0,3632,8,16,0,0,3648,8,16,0,0,3664,8,16,0,0,3680,8,16,0,0,3696,8,16,0,0,3712,8,16,0,0,3728,8,16,0,0,3744,8,16,0,0,3760,8,16,0,0,3776,8,16,0,0,3792,8,16,0,0,3808,8,16,0,0,3824,8,16,0,0,3840,8,16,0,0,3856,8,16,0,0,3872,8,16,0,0,3888,8,16,0,0,3904,8,16,0,0,3920,8,16,0,0,3936,8,16,0,0,3952,8,16,0,0,3968,8,16,0,0,3984,8,16,0,0,4000,8,16,0,0,4016,8,16,0,0,4032,8,16,0,0,4048,8,16,0,0,4064,8,16,0,0,4080,8,16,0,0,}; +static rfbFontData default8x16Font = { default8x16FontData, default8x16FontMetaData }; + +#endif diff --git a/rfb/keysym.h b/rfb/keysym.h new file mode 100644 index 0000000..92d5158 --- /dev/null +++ b/rfb/keysym.h @@ -0,0 +1,1638 @@ +#ifndef XK_0 + +/* $XConsortium: keysym.h,v 1.15 94/04/17 20:10:55 rws Exp $ */ + +/*********************************************************** + +Copyright (c) 1987 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* default keysyms */ +#define XK_MISCELLANY +#define XK_XKB_KEYS +#define XK_LATIN1 +#define XK_LATIN2 +#define XK_LATIN3 +#define XK_LATIN4 +#define XK_GREEK + +/* $TOG: keysymdef.h /main/25 1997/06/21 10:54:51 kaleb $ */ + +/*********************************************************** +Copyright (c) 1987, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from the X Consortium. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#define XK_VoidSymbol 0xFFFFFF /* void symbol */ + +#ifdef XK_MISCELLANY +/* + * TTY Functions, cleverly chosen to map to ascii, for convenience of + * programming, but could have been arbitrary (at the cost of lookup + * tables in client code. + */ + +#define XK_BackSpace 0xFF08 /* back space, back char */ +#define XK_Tab 0xFF09 +#define XK_Linefeed 0xFF0A /* Linefeed, LF */ +#define XK_Clear 0xFF0B +#define XK_Return 0xFF0D /* Return, enter */ +#define XK_Pause 0xFF13 /* Pause, hold */ +#define XK_Scroll_Lock 0xFF14 +#define XK_Sys_Req 0xFF15 +#define XK_Escape 0xFF1B +#define XK_Delete 0xFFFF /* Delete, rubout */ + + + +/* International & multi-key character composition */ + +#define XK_Multi_key 0xFF20 /* Multi-key character compose */ +#define XK_SingleCandidate 0xFF3C +#define XK_MultipleCandidate 0xFF3D +#define XK_PreviousCandidate 0xFF3E + +/* Japanese keyboard support */ + +#define XK_Kanji 0xFF21 /* Kanji, Kanji convert */ +#define XK_Muhenkan 0xFF22 /* Cancel Conversion */ +#define XK_Henkan_Mode 0xFF23 /* Start/Stop Conversion */ +#define XK_Henkan 0xFF23 /* Alias for Henkan_Mode */ +#define XK_Romaji 0xFF24 /* to Romaji */ +#define XK_Hiragana 0xFF25 /* to Hiragana */ +#define XK_Katakana 0xFF26 /* to Katakana */ +#define XK_Hiragana_Katakana 0xFF27 /* Hiragana/Katakana toggle */ +#define XK_Zenkaku 0xFF28 /* to Zenkaku */ +#define XK_Hankaku 0xFF29 /* to Hankaku */ +#define XK_Zenkaku_Hankaku 0xFF2A /* Zenkaku/Hankaku toggle */ +#define XK_Touroku 0xFF2B /* Add to Dictionary */ +#define XK_Massyo 0xFF2C /* Delete from Dictionary */ +#define XK_Kana_Lock 0xFF2D /* Kana Lock */ +#define XK_Kana_Shift 0xFF2E /* Kana Shift */ +#define XK_Eisu_Shift 0xFF2F /* Alphanumeric Shift */ +#define XK_Eisu_toggle 0xFF30 /* Alphanumeric toggle */ +#define XK_Zen_Koho 0xFF3D /* Multiple/All Candidate(s) */ +#define XK_Mae_Koho 0xFF3E /* Previous Candidate */ + +/* 0xFF31 through 0xFF3F are under XK_KOREAN */ + +/* Cursor control & motion */ + +#define XK_Home 0xFF50 +#define XK_Left 0xFF51 /* Move left, left arrow */ +#define XK_Up 0xFF52 /* Move up, up arrow */ +#define XK_Right 0xFF53 /* Move right, right arrow */ +#define XK_Down 0xFF54 /* Move down, down arrow */ +#define XK_Prior 0xFF55 /* Prior, previous */ +#define XK_Page_Up 0xFF55 +#define XK_Next 0xFF56 /* Next */ +#define XK_Page_Down 0xFF56 +#define XK_End 0xFF57 /* EOL */ +#define XK_Begin 0xFF58 /* BOL */ + + +/* Misc Functions */ + +#define XK_Select 0xFF60 /* Select, mark */ +#define XK_Print 0xFF61 +#define XK_Execute 0xFF62 /* Execute, run, do */ +#define XK_Insert 0xFF63 /* Insert, insert here */ +#define XK_Undo 0xFF65 /* Undo, oops */ +#define XK_Redo 0xFF66 /* redo, again */ +#define XK_Menu 0xFF67 +#define XK_Find 0xFF68 /* Find, search */ +#define XK_Cancel 0xFF69 /* Cancel, stop, abort, exit */ +#define XK_Help 0xFF6A /* Help */ +#define XK_Break 0xFF6B +#define XK_Mode_switch 0xFF7E /* Character set switch */ +#define XK_script_switch 0xFF7E /* Alias for mode_switch */ +#define XK_Num_Lock 0xFF7F + +/* Keypad Functions, keypad numbers cleverly chosen to map to ascii */ + +#define XK_KP_Space 0xFF80 /* space */ +#define XK_KP_Tab 0xFF89 +#define XK_KP_Enter 0xFF8D /* enter */ +#define XK_KP_F1 0xFF91 /* PF1, KP_A, ... */ +#define XK_KP_F2 0xFF92 +#define XK_KP_F3 0xFF93 +#define XK_KP_F4 0xFF94 +#define XK_KP_Home 0xFF95 +#define XK_KP_Left 0xFF96 +#define XK_KP_Up 0xFF97 +#define XK_KP_Right 0xFF98 +#define XK_KP_Down 0xFF99 +#define XK_KP_Prior 0xFF9A +#define XK_KP_Page_Up 0xFF9A +#define XK_KP_Next 0xFF9B +#define XK_KP_Page_Down 0xFF9B +#define XK_KP_End 0xFF9C +#define XK_KP_Begin 0xFF9D +#define XK_KP_Insert 0xFF9E +#define XK_KP_Delete 0xFF9F +#define XK_KP_Equal 0xFFBD /* equals */ +#define XK_KP_Multiply 0xFFAA +#define XK_KP_Add 0xFFAB +#define XK_KP_Separator 0xFFAC /* separator, often comma */ +#define XK_KP_Subtract 0xFFAD +#define XK_KP_Decimal 0xFFAE +#define XK_KP_Divide 0xFFAF + +#define XK_KP_0 0xFFB0 +#define XK_KP_1 0xFFB1 +#define XK_KP_2 0xFFB2 +#define XK_KP_3 0xFFB3 +#define XK_KP_4 0xFFB4 +#define XK_KP_5 0xFFB5 +#define XK_KP_6 0xFFB6 +#define XK_KP_7 0xFFB7 +#define XK_KP_8 0xFFB8 +#define XK_KP_9 0xFFB9 + + + +/* + * Auxiliary Functions; note the duplicate definitions for left and right + * function keys; Sun keyboards and a few other manufactures have such + * function key groups on the left and/or right sides of the keyboard. + * We've not found a keyboard with more than 35 function keys total. + */ + +#define XK_F1 0xFFBE +#define XK_F2 0xFFBF +#define XK_F3 0xFFC0 +#define XK_F4 0xFFC1 +#define XK_F5 0xFFC2 +#define XK_F6 0xFFC3 +#define XK_F7 0xFFC4 +#define XK_F8 0xFFC5 +#define XK_F9 0xFFC6 +#define XK_F10 0xFFC7 +#define XK_F11 0xFFC8 +#define XK_L1 0xFFC8 +#define XK_F12 0xFFC9 +#define XK_L2 0xFFC9 +#define XK_F13 0xFFCA +#define XK_L3 0xFFCA +#define XK_F14 0xFFCB +#define XK_L4 0xFFCB +#define XK_F15 0xFFCC +#define XK_L5 0xFFCC +#define XK_F16 0xFFCD +#define XK_L6 0xFFCD +#define XK_F17 0xFFCE +#define XK_L7 0xFFCE +#define XK_F18 0xFFCF +#define XK_L8 0xFFCF +#define XK_F19 0xFFD0 +#define XK_L9 0xFFD0 +#define XK_F20 0xFFD1 +#define XK_L10 0xFFD1 +#define XK_F21 0xFFD2 +#define XK_R1 0xFFD2 +#define XK_F22 0xFFD3 +#define XK_R2 0xFFD3 +#define XK_F23 0xFFD4 +#define XK_R3 0xFFD4 +#define XK_F24 0xFFD5 +#define XK_R4 0xFFD5 +#define XK_F25 0xFFD6 +#define XK_R5 0xFFD6 +#define XK_F26 0xFFD7 +#define XK_R6 0xFFD7 +#define XK_F27 0xFFD8 +#define XK_R7 0xFFD8 +#define XK_F28 0xFFD9 +#define XK_R8 0xFFD9 +#define XK_F29 0xFFDA +#define XK_R9 0xFFDA +#define XK_F30 0xFFDB +#define XK_R10 0xFFDB +#define XK_F31 0xFFDC +#define XK_R11 0xFFDC +#define XK_F32 0xFFDD +#define XK_R12 0xFFDD +#define XK_F33 0xFFDE +#define XK_R13 0xFFDE +#define XK_F34 0xFFDF +#define XK_R14 0xFFDF +#define XK_F35 0xFFE0 +#define XK_R15 0xFFE0 + +/* Modifiers */ + +#define XK_Shift_L 0xFFE1 /* Left shift */ +#define XK_Shift_R 0xFFE2 /* Right shift */ +#define XK_Control_L 0xFFE3 /* Left control */ +#define XK_Control_R 0xFFE4 /* Right control */ +#define XK_Caps_Lock 0xFFE5 /* Caps lock */ +#define XK_Shift_Lock 0xFFE6 /* Shift lock */ + +#define XK_Meta_L 0xFFE7 /* Left meta */ +#define XK_Meta_R 0xFFE8 /* Right meta */ +#define XK_Alt_L 0xFFE9 /* Left alt */ +#define XK_Alt_R 0xFFEA /* Right alt */ +#define XK_Super_L 0xFFEB /* Left super */ +#define XK_Super_R 0xFFEC /* Right super */ +#define XK_Hyper_L 0xFFED /* Left hyper */ +#define XK_Hyper_R 0xFFEE /* Right hyper */ +#endif /* XK_MISCELLANY */ + +/* + * ISO 9995 Function and Modifier Keys + * Byte 3 = 0xFE + */ + +#ifdef XK_XKB_KEYS +#define XK_ISO_Lock 0xFE01 +#define XK_ISO_Level2_Latch 0xFE02 +#define XK_ISO_Level3_Shift 0xFE03 +#define XK_ISO_Level3_Latch 0xFE04 +#define XK_ISO_Level3_Lock 0xFE05 +#define XK_ISO_Group_Shift 0xFF7E /* Alias for mode_switch */ +#define XK_ISO_Group_Latch 0xFE06 +#define XK_ISO_Group_Lock 0xFE07 +#define XK_ISO_Next_Group 0xFE08 +#define XK_ISO_Next_Group_Lock 0xFE09 +#define XK_ISO_Prev_Group 0xFE0A +#define XK_ISO_Prev_Group_Lock 0xFE0B +#define XK_ISO_First_Group 0xFE0C +#define XK_ISO_First_Group_Lock 0xFE0D +#define XK_ISO_Last_Group 0xFE0E +#define XK_ISO_Last_Group_Lock 0xFE0F + +#define XK_ISO_Left_Tab 0xFE20 +#define XK_ISO_Move_Line_Up 0xFE21 +#define XK_ISO_Move_Line_Down 0xFE22 +#define XK_ISO_Partial_Line_Up 0xFE23 +#define XK_ISO_Partial_Line_Down 0xFE24 +#define XK_ISO_Partial_Space_Left 0xFE25 +#define XK_ISO_Partial_Space_Right 0xFE26 +#define XK_ISO_Set_Margin_Left 0xFE27 +#define XK_ISO_Set_Margin_Right 0xFE28 +#define XK_ISO_Release_Margin_Left 0xFE29 +#define XK_ISO_Release_Margin_Right 0xFE2A +#define XK_ISO_Release_Both_Margins 0xFE2B +#define XK_ISO_Fast_Cursor_Left 0xFE2C +#define XK_ISO_Fast_Cursor_Right 0xFE2D +#define XK_ISO_Fast_Cursor_Up 0xFE2E +#define XK_ISO_Fast_Cursor_Down 0xFE2F +#define XK_ISO_Continuous_Underline 0xFE30 +#define XK_ISO_Discontinuous_Underline 0xFE31 +#define XK_ISO_Emphasize 0xFE32 +#define XK_ISO_Center_Object 0xFE33 +#define XK_ISO_Enter 0xFE34 + +#define XK_dead_grave 0xFE50 +#define XK_dead_acute 0xFE51 +#define XK_dead_circumflex 0xFE52 +#define XK_dead_tilde 0xFE53 +#define XK_dead_macron 0xFE54 +#define XK_dead_breve 0xFE55 +#define XK_dead_abovedot 0xFE56 +#define XK_dead_diaeresis 0xFE57 +#define XK_dead_abovering 0xFE58 +#define XK_dead_doubleacute 0xFE59 +#define XK_dead_caron 0xFE5A +#define XK_dead_cedilla 0xFE5B +#define XK_dead_ogonek 0xFE5C +#define XK_dead_iota 0xFE5D +#define XK_dead_voiced_sound 0xFE5E +#define XK_dead_semivoiced_sound 0xFE5F +#define XK_dead_belowdot 0xFE60 + +#define XK_First_Virtual_Screen 0xFED0 +#define XK_Prev_Virtual_Screen 0xFED1 +#define XK_Next_Virtual_Screen 0xFED2 +#define XK_Last_Virtual_Screen 0xFED4 +#define XK_Terminate_Server 0xFED5 + +#define XK_AccessX_Enable 0xFE70 +#define XK_AccessX_Feedback_Enable 0xFE71 +#define XK_RepeatKeys_Enable 0xFE72 +#define XK_SlowKeys_Enable 0xFE73 +#define XK_BounceKeys_Enable 0xFE74 +#define XK_StickyKeys_Enable 0xFE75 +#define XK_MouseKeys_Enable 0xFE76 +#define XK_MouseKeys_Accel_Enable 0xFE77 +#define XK_Overlay1_Enable 0xFE78 +#define XK_Overlay2_Enable 0xFE79 +#define XK_AudibleBell_Enable 0xFE7A + +#define XK_Pointer_Left 0xFEE0 +#define XK_Pointer_Right 0xFEE1 +#define XK_Pointer_Up 0xFEE2 +#define XK_Pointer_Down 0xFEE3 +#define XK_Pointer_UpLeft 0xFEE4 +#define XK_Pointer_UpRight 0xFEE5 +#define XK_Pointer_DownLeft 0xFEE6 +#define XK_Pointer_DownRight 0xFEE7 +#define XK_Pointer_Button_Dflt 0xFEE8 +#define XK_Pointer_Button1 0xFEE9 +#define XK_Pointer_Button2 0xFEEA +#define XK_Pointer_Button3 0xFEEB +#define XK_Pointer_Button4 0xFEEC +#define XK_Pointer_Button5 0xFEED +#define XK_Pointer_DblClick_Dflt 0xFEEE +#define XK_Pointer_DblClick1 0xFEEF +#define XK_Pointer_DblClick2 0xFEF0 +#define XK_Pointer_DblClick3 0xFEF1 +#define XK_Pointer_DblClick4 0xFEF2 +#define XK_Pointer_DblClick5 0xFEF3 +#define XK_Pointer_Drag_Dflt 0xFEF4 +#define XK_Pointer_Drag1 0xFEF5 +#define XK_Pointer_Drag2 0xFEF6 +#define XK_Pointer_Drag3 0xFEF7 +#define XK_Pointer_Drag4 0xFEF8 +#define XK_Pointer_Drag5 0xFEFD + +#define XK_Pointer_EnableKeys 0xFEF9 +#define XK_Pointer_Accelerate 0xFEFA +#define XK_Pointer_DfltBtnNext 0xFEFB +#define XK_Pointer_DfltBtnPrev 0xFEFC + +#endif + +/* + * 3270 Terminal Keys + * Byte 3 = 0xFD + */ + +#ifdef XK_3270 +#define XK_3270_Duplicate 0xFD01 +#define XK_3270_FieldMark 0xFD02 +#define XK_3270_Right2 0xFD03 +#define XK_3270_Left2 0xFD04 +#define XK_3270_BackTab 0xFD05 +#define XK_3270_EraseEOF 0xFD06 +#define XK_3270_EraseInput 0xFD07 +#define XK_3270_Reset 0xFD08 +#define XK_3270_Quit 0xFD09 +#define XK_3270_PA1 0xFD0A +#define XK_3270_PA2 0xFD0B +#define XK_3270_PA3 0xFD0C +#define XK_3270_Test 0xFD0D +#define XK_3270_Attn 0xFD0E +#define XK_3270_CursorBlink 0xFD0F +#define XK_3270_AltCursor 0xFD10 +#define XK_3270_KeyClick 0xFD11 +#define XK_3270_Jump 0xFD12 +#define XK_3270_Ident 0xFD13 +#define XK_3270_Rule 0xFD14 +#define XK_3270_Copy 0xFD15 +#define XK_3270_Play 0xFD16 +#define XK_3270_Setup 0xFD17 +#define XK_3270_Record 0xFD18 +#define XK_3270_ChangeScreen 0xFD19 +#define XK_3270_DeleteWord 0xFD1A +#define XK_3270_ExSelect 0xFD1B +#define XK_3270_CursorSelect 0xFD1C +#define XK_3270_PrintScreen 0xFD1D +#define XK_3270_Enter 0xFD1E +#endif + +/* + * Latin 1 + * Byte 3 = 0 + */ +#ifdef XK_LATIN1 +#define XK_space 0x020 +#define XK_exclam 0x021 +#define XK_quotedbl 0x022 +#define XK_numbersign 0x023 +#define XK_dollar 0x024 +#define XK_percent 0x025 +#define XK_ampersand 0x026 +#define XK_apostrophe 0x027 +#define XK_quoteright 0x027 /* deprecated */ +#define XK_parenleft 0x028 +#define XK_parenright 0x029 +#define XK_asterisk 0x02a +#define XK_plus 0x02b +#define XK_comma 0x02c +#define XK_minus 0x02d +#define XK_period 0x02e +#define XK_slash 0x02f +#define XK_0 0x030 +#define XK_1 0x031 +#define XK_2 0x032 +#define XK_3 0x033 +#define XK_4 0x034 +#define XK_5 0x035 +#define XK_6 0x036 +#define XK_7 0x037 +#define XK_8 0x038 +#define XK_9 0x039 +#define XK_colon 0x03a +#define XK_semicolon 0x03b +#define XK_less 0x03c +#define XK_equal 0x03d +#define XK_greater 0x03e +#define XK_question 0x03f +#define XK_at 0x040 +#define XK_A 0x041 +#define XK_B 0x042 +#define XK_C 0x043 +#define XK_D 0x044 +#define XK_E 0x045 +#define XK_F 0x046 +#define XK_G 0x047 +#define XK_H 0x048 +#define XK_I 0x049 +#define XK_J 0x04a +#define XK_K 0x04b +#define XK_L 0x04c +#define XK_M 0x04d +#define XK_N 0x04e +#define XK_O 0x04f +#define XK_P 0x050 +#define XK_Q 0x051 +#define XK_R 0x052 +#define XK_S 0x053 +#define XK_T 0x054 +#define XK_U 0x055 +#define XK_V 0x056 +#define XK_W 0x057 +#define XK_X 0x058 +#define XK_Y 0x059 +#define XK_Z 0x05a +#define XK_bracketleft 0x05b +#define XK_backslash 0x05c +#define XK_bracketright 0x05d +#define XK_asciicircum 0x05e +#define XK_underscore 0x05f +#define XK_grave 0x060 +#define XK_quoteleft 0x060 /* deprecated */ +#define XK_a 0x061 +#define XK_b 0x062 +#define XK_c 0x063 +#define XK_d 0x064 +#define XK_e 0x065 +#define XK_f 0x066 +#define XK_g 0x067 +#define XK_h 0x068 +#define XK_i 0x069 +#define XK_j 0x06a +#define XK_k 0x06b +#define XK_l 0x06c +#define XK_m 0x06d +#define XK_n 0x06e +#define XK_o 0x06f +#define XK_p 0x070 +#define XK_q 0x071 +#define XK_r 0x072 +#define XK_s 0x073 +#define XK_t 0x074 +#define XK_u 0x075 +#define XK_v 0x076 +#define XK_w 0x077 +#define XK_x 0x078 +#define XK_y 0x079 +#define XK_z 0x07a +#define XK_braceleft 0x07b +#define XK_bar 0x07c +#define XK_braceright 0x07d +#define XK_asciitilde 0x07e + +#define XK_nobreakspace 0x0a0 +#define XK_exclamdown 0x0a1 +#define XK_cent 0x0a2 +#define XK_sterling 0x0a3 +#define XK_currency 0x0a4 +#define XK_yen 0x0a5 +#define XK_brokenbar 0x0a6 +#define XK_section 0x0a7 +#define XK_diaeresis 0x0a8 +#define XK_copyright 0x0a9 +#define XK_ordfeminine 0x0aa +#define XK_guillemotleft 0x0ab /* left angle quotation mark */ +#define XK_notsign 0x0ac +#define XK_hyphen 0x0ad +#define XK_registered 0x0ae +#define XK_macron 0x0af +#define XK_degree 0x0b0 +#define XK_plusminus 0x0b1 +#define XK_twosuperior 0x0b2 +#define XK_threesuperior 0x0b3 +#define XK_acute 0x0b4 +#define XK_mu 0x0b5 +#define XK_paragraph 0x0b6 +#define XK_periodcentered 0x0b7 +#define XK_cedilla 0x0b8 +#define XK_onesuperior 0x0b9 +#define XK_masculine 0x0ba +#define XK_guillemotright 0x0bb /* right angle quotation mark */ +#define XK_onequarter 0x0bc +#define XK_onehalf 0x0bd +#define XK_threequarters 0x0be +#define XK_questiondown 0x0bf +#define XK_Agrave 0x0c0 +#define XK_Aacute 0x0c1 +#define XK_Acircumflex 0x0c2 +#define XK_Atilde 0x0c3 +#define XK_Adiaeresis 0x0c4 +#define XK_Aring 0x0c5 +#define XK_AE 0x0c6 +#define XK_Ccedilla 0x0c7 +#define XK_Egrave 0x0c8 +#define XK_Eacute 0x0c9 +#define XK_Ecircumflex 0x0ca +#define XK_Ediaeresis 0x0cb +#define XK_Igrave 0x0cc +#define XK_Iacute 0x0cd +#define XK_Icircumflex 0x0ce +#define XK_Idiaeresis 0x0cf +#define XK_ETH 0x0d0 +#define XK_Eth 0x0d0 /* deprecated */ +#define XK_Ntilde 0x0d1 +#define XK_Ograve 0x0d2 +#define XK_Oacute 0x0d3 +#define XK_Ocircumflex 0x0d4 +#define XK_Otilde 0x0d5 +#define XK_Odiaeresis 0x0d6 +#define XK_multiply 0x0d7 +#define XK_Ooblique 0x0d8 +#define XK_Ugrave 0x0d9 +#define XK_Uacute 0x0da +#define XK_Ucircumflex 0x0db +#define XK_Udiaeresis 0x0dc +#define XK_Yacute 0x0dd +#define XK_THORN 0x0de +#define XK_Thorn 0x0de /* deprecated */ +#define XK_ssharp 0x0df +#define XK_agrave 0x0e0 +#define XK_aacute 0x0e1 +#define XK_acircumflex 0x0e2 +#define XK_atilde 0x0e3 +#define XK_adiaeresis 0x0e4 +#define XK_aring 0x0e5 +#define XK_ae 0x0e6 +#define XK_ccedilla 0x0e7 +#define XK_egrave 0x0e8 +#define XK_eacute 0x0e9 +#define XK_ecircumflex 0x0ea +#define XK_ediaeresis 0x0eb +#define XK_igrave 0x0ec +#define XK_iacute 0x0ed +#define XK_icircumflex 0x0ee +#define XK_idiaeresis 0x0ef +#define XK_eth 0x0f0 +#define XK_ntilde 0x0f1 +#define XK_ograve 0x0f2 +#define XK_oacute 0x0f3 +#define XK_ocircumflex 0x0f4 +#define XK_otilde 0x0f5 +#define XK_odiaeresis 0x0f6 +#define XK_division 0x0f7 +#define XK_oslash 0x0f8 +#define XK_ugrave 0x0f9 +#define XK_uacute 0x0fa +#define XK_ucircumflex 0x0fb +#define XK_udiaeresis 0x0fc +#define XK_yacute 0x0fd +#define XK_thorn 0x0fe +#define XK_ydiaeresis 0x0ff +#endif /* XK_LATIN1 */ + +/* + * Latin 2 + * Byte 3 = 1 + */ + +#ifdef XK_LATIN2 +#define XK_Aogonek 0x1a1 +#define XK_breve 0x1a2 +#define XK_Lstroke 0x1a3 +#define XK_Lcaron 0x1a5 +#define XK_Sacute 0x1a6 +#define XK_Scaron 0x1a9 +#define XK_Scedilla 0x1aa +#define XK_Tcaron 0x1ab +#define XK_Zacute 0x1ac +#define XK_Zcaron 0x1ae +#define XK_Zabovedot 0x1af +#define XK_aogonek 0x1b1 +#define XK_ogonek 0x1b2 +#define XK_lstroke 0x1b3 +#define XK_lcaron 0x1b5 +#define XK_sacute 0x1b6 +#define XK_caron 0x1b7 +#define XK_scaron 0x1b9 +#define XK_scedilla 0x1ba +#define XK_tcaron 0x1bb +#define XK_zacute 0x1bc +#define XK_doubleacute 0x1bd +#define XK_zcaron 0x1be +#define XK_zabovedot 0x1bf +#define XK_Racute 0x1c0 +#define XK_Abreve 0x1c3 +#define XK_Lacute 0x1c5 +#define XK_Cacute 0x1c6 +#define XK_Ccaron 0x1c8 +#define XK_Eogonek 0x1ca +#define XK_Ecaron 0x1cc +#define XK_Dcaron 0x1cf +#define XK_Dstroke 0x1d0 +#define XK_Nacute 0x1d1 +#define XK_Ncaron 0x1d2 +#define XK_Odoubleacute 0x1d5 +#define XK_Rcaron 0x1d8 +#define XK_Uring 0x1d9 +#define XK_Udoubleacute 0x1db +#define XK_Tcedilla 0x1de +#define XK_racute 0x1e0 +#define XK_abreve 0x1e3 +#define XK_lacute 0x1e5 +#define XK_cacute 0x1e6 +#define XK_ccaron 0x1e8 +#define XK_eogonek 0x1ea +#define XK_ecaron 0x1ec +#define XK_dcaron 0x1ef +#define XK_dstroke 0x1f0 +#define XK_nacute 0x1f1 +#define XK_ncaron 0x1f2 +#define XK_odoubleacute 0x1f5 +#define XK_udoubleacute 0x1fb +#define XK_rcaron 0x1f8 +#define XK_uring 0x1f9 +#define XK_tcedilla 0x1fe +#define XK_abovedot 0x1ff +#endif /* XK_LATIN2 */ + +/* + * Latin 3 + * Byte 3 = 2 + */ + +#ifdef XK_LATIN3 +#define XK_Hstroke 0x2a1 +#define XK_Hcircumflex 0x2a6 +#define XK_Iabovedot 0x2a9 +#define XK_Gbreve 0x2ab +#define XK_Jcircumflex 0x2ac +#define XK_hstroke 0x2b1 +#define XK_hcircumflex 0x2b6 +#define XK_idotless 0x2b9 +#define XK_gbreve 0x2bb +#define XK_jcircumflex 0x2bc +#define XK_Cabovedot 0x2c5 +#define XK_Ccircumflex 0x2c6 +#define XK_Gabovedot 0x2d5 +#define XK_Gcircumflex 0x2d8 +#define XK_Ubreve 0x2dd +#define XK_Scircumflex 0x2de +#define XK_cabovedot 0x2e5 +#define XK_ccircumflex 0x2e6 +#define XK_gabovedot 0x2f5 +#define XK_gcircumflex 0x2f8 +#define XK_ubreve 0x2fd +#define XK_scircumflex 0x2fe +#endif /* XK_LATIN3 */ + + +/* + * Latin 4 + * Byte 3 = 3 + */ + +#ifdef XK_LATIN4 +#define XK_kra 0x3a2 +#define XK_kappa 0x3a2 /* deprecated */ +#define XK_Rcedilla 0x3a3 +#define XK_Itilde 0x3a5 +#define XK_Lcedilla 0x3a6 +#define XK_Emacron 0x3aa +#define XK_Gcedilla 0x3ab +#define XK_Tslash 0x3ac +#define XK_rcedilla 0x3b3 +#define XK_itilde 0x3b5 +#define XK_lcedilla 0x3b6 +#define XK_emacron 0x3ba +#define XK_gcedilla 0x3bb +#define XK_tslash 0x3bc +#define XK_ENG 0x3bd +#define XK_eng 0x3bf +#define XK_Amacron 0x3c0 +#define XK_Iogonek 0x3c7 +#define XK_Eabovedot 0x3cc +#define XK_Imacron 0x3cf +#define XK_Ncedilla 0x3d1 +#define XK_Omacron 0x3d2 +#define XK_Kcedilla 0x3d3 +#define XK_Uogonek 0x3d9 +#define XK_Utilde 0x3dd +#define XK_Umacron 0x3de +#define XK_amacron 0x3e0 +#define XK_iogonek 0x3e7 +#define XK_eabovedot 0x3ec +#define XK_imacron 0x3ef +#define XK_ncedilla 0x3f1 +#define XK_omacron 0x3f2 +#define XK_kcedilla 0x3f3 +#define XK_uogonek 0x3f9 +#define XK_utilde 0x3fd +#define XK_umacron 0x3fe +#endif /* XK_LATIN4 */ + +/* + * Katakana + * Byte 3 = 4 + */ + +#ifdef XK_KATAKANA +#define XK_overline 0x47e +#define XK_kana_fullstop 0x4a1 +#define XK_kana_openingbracket 0x4a2 +#define XK_kana_closingbracket 0x4a3 +#define XK_kana_comma 0x4a4 +#define XK_kana_conjunctive 0x4a5 +#define XK_kana_middledot 0x4a5 /* deprecated */ +#define XK_kana_WO 0x4a6 +#define XK_kana_a 0x4a7 +#define XK_kana_i 0x4a8 +#define XK_kana_u 0x4a9 +#define XK_kana_e 0x4aa +#define XK_kana_o 0x4ab +#define XK_kana_ya 0x4ac +#define XK_kana_yu 0x4ad +#define XK_kana_yo 0x4ae +#define XK_kana_tsu 0x4af +#define XK_kana_tu 0x4af /* deprecated */ +#define XK_prolongedsound 0x4b0 +#define XK_kana_A 0x4b1 +#define XK_kana_I 0x4b2 +#define XK_kana_U 0x4b3 +#define XK_kana_E 0x4b4 +#define XK_kana_O 0x4b5 +#define XK_kana_KA 0x4b6 +#define XK_kana_KI 0x4b7 +#define XK_kana_KU 0x4b8 +#define XK_kana_KE 0x4b9 +#define XK_kana_KO 0x4ba +#define XK_kana_SA 0x4bb +#define XK_kana_SHI 0x4bc +#define XK_kana_SU 0x4bd +#define XK_kana_SE 0x4be +#define XK_kana_SO 0x4bf +#define XK_kana_TA 0x4c0 +#define XK_kana_CHI 0x4c1 +#define XK_kana_TI 0x4c1 /* deprecated */ +#define XK_kana_TSU 0x4c2 +#define XK_kana_TU 0x4c2 /* deprecated */ +#define XK_kana_TE 0x4c3 +#define XK_kana_TO 0x4c4 +#define XK_kana_NA 0x4c5 +#define XK_kana_NI 0x4c6 +#define XK_kana_NU 0x4c7 +#define XK_kana_NE 0x4c8 +#define XK_kana_NO 0x4c9 +#define XK_kana_HA 0x4ca +#define XK_kana_HI 0x4cb +#define XK_kana_FU 0x4cc +#define XK_kana_HU 0x4cc /* deprecated */ +#define XK_kana_HE 0x4cd +#define XK_kana_HO 0x4ce +#define XK_kana_MA 0x4cf +#define XK_kana_MI 0x4d0 +#define XK_kana_MU 0x4d1 +#define XK_kana_ME 0x4d2 +#define XK_kana_MO 0x4d3 +#define XK_kana_YA 0x4d4 +#define XK_kana_YU 0x4d5 +#define XK_kana_YO 0x4d6 +#define XK_kana_RA 0x4d7 +#define XK_kana_RI 0x4d8 +#define XK_kana_RU 0x4d9 +#define XK_kana_RE 0x4da +#define XK_kana_RO 0x4db +#define XK_kana_WA 0x4dc +#define XK_kana_N 0x4dd +#define XK_voicedsound 0x4de +#define XK_semivoicedsound 0x4df +#define XK_kana_switch 0xFF7E /* Alias for mode_switch */ +#endif /* XK_KATAKANA */ + +/* + * Arabic + * Byte 3 = 5 + */ + +#ifdef XK_ARABIC +#define XK_Arabic_comma 0x5ac +#define XK_Arabic_semicolon 0x5bb +#define XK_Arabic_question_mark 0x5bf +#define XK_Arabic_hamza 0x5c1 +#define XK_Arabic_maddaonalef 0x5c2 +#define XK_Arabic_hamzaonalef 0x5c3 +#define XK_Arabic_hamzaonwaw 0x5c4 +#define XK_Arabic_hamzaunderalef 0x5c5 +#define XK_Arabic_hamzaonyeh 0x5c6 +#define XK_Arabic_alef 0x5c7 +#define XK_Arabic_beh 0x5c8 +#define XK_Arabic_tehmarbuta 0x5c9 +#define XK_Arabic_teh 0x5ca +#define XK_Arabic_theh 0x5cb +#define XK_Arabic_jeem 0x5cc +#define XK_Arabic_hah 0x5cd +#define XK_Arabic_khah 0x5ce +#define XK_Arabic_dal 0x5cf +#define XK_Arabic_thal 0x5d0 +#define XK_Arabic_ra 0x5d1 +#define XK_Arabic_zain 0x5d2 +#define XK_Arabic_seen 0x5d3 +#define XK_Arabic_sheen 0x5d4 +#define XK_Arabic_sad 0x5d5 +#define XK_Arabic_dad 0x5d6 +#define XK_Arabic_tah 0x5d7 +#define XK_Arabic_zah 0x5d8 +#define XK_Arabic_ain 0x5d9 +#define XK_Arabic_ghain 0x5da +#define XK_Arabic_tatweel 0x5e0 +#define XK_Arabic_feh 0x5e1 +#define XK_Arabic_qaf 0x5e2 +#define XK_Arabic_kaf 0x5e3 +#define XK_Arabic_lam 0x5e4 +#define XK_Arabic_meem 0x5e5 +#define XK_Arabic_noon 0x5e6 +#define XK_Arabic_ha 0x5e7 +#define XK_Arabic_heh 0x5e7 /* deprecated */ +#define XK_Arabic_waw 0x5e8 +#define XK_Arabic_alefmaksura 0x5e9 +#define XK_Arabic_yeh 0x5ea +#define XK_Arabic_fathatan 0x5eb +#define XK_Arabic_dammatan 0x5ec +#define XK_Arabic_kasratan 0x5ed +#define XK_Arabic_fatha 0x5ee +#define XK_Arabic_damma 0x5ef +#define XK_Arabic_kasra 0x5f0 +#define XK_Arabic_shadda 0x5f1 +#define XK_Arabic_sukun 0x5f2 +#define XK_Arabic_switch 0xFF7E /* Alias for mode_switch */ +#endif /* XK_ARABIC */ + +/* + * Cyrillic + * Byte 3 = 6 + */ +#ifdef XK_CYRILLIC +#define XK_Serbian_dje 0x6a1 +#define XK_Macedonia_gje 0x6a2 +#define XK_Cyrillic_io 0x6a3 +#define XK_Ukrainian_ie 0x6a4 +#define XK_Ukranian_je 0x6a4 /* deprecated */ +#define XK_Macedonia_dse 0x6a5 +#define XK_Ukrainian_i 0x6a6 +#define XK_Ukranian_i 0x6a6 /* deprecated */ +#define XK_Ukrainian_yi 0x6a7 +#define XK_Ukranian_yi 0x6a7 /* deprecated */ +#define XK_Cyrillic_je 0x6a8 +#define XK_Serbian_je 0x6a8 /* deprecated */ +#define XK_Cyrillic_lje 0x6a9 +#define XK_Serbian_lje 0x6a9 /* deprecated */ +#define XK_Cyrillic_nje 0x6aa +#define XK_Serbian_nje 0x6aa /* deprecated */ +#define XK_Serbian_tshe 0x6ab +#define XK_Macedonia_kje 0x6ac +#define XK_Byelorussian_shortu 0x6ae +#define XK_Cyrillic_dzhe 0x6af +#define XK_Serbian_dze 0x6af /* deprecated */ +#define XK_numerosign 0x6b0 +#define XK_Serbian_DJE 0x6b1 +#define XK_Macedonia_GJE 0x6b2 +#define XK_Cyrillic_IO 0x6b3 +#define XK_Ukrainian_IE 0x6b4 +#define XK_Ukranian_JE 0x6b4 /* deprecated */ +#define XK_Macedonia_DSE 0x6b5 +#define XK_Ukrainian_I 0x6b6 +#define XK_Ukranian_I 0x6b6 /* deprecated */ +#define XK_Ukrainian_YI 0x6b7 +#define XK_Ukranian_YI 0x6b7 /* deprecated */ +#define XK_Cyrillic_JE 0x6b8 +#define XK_Serbian_JE 0x6b8 /* deprecated */ +#define XK_Cyrillic_LJE 0x6b9 +#define XK_Serbian_LJE 0x6b9 /* deprecated */ +#define XK_Cyrillic_NJE 0x6ba +#define XK_Serbian_NJE 0x6ba /* deprecated */ +#define XK_Serbian_TSHE 0x6bb +#define XK_Macedonia_KJE 0x6bc +#define XK_Byelorussian_SHORTU 0x6be +#define XK_Cyrillic_DZHE 0x6bf +#define XK_Serbian_DZE 0x6bf /* deprecated */ +#define XK_Cyrillic_yu 0x6c0 +#define XK_Cyrillic_a 0x6c1 +#define XK_Cyrillic_be 0x6c2 +#define XK_Cyrillic_tse 0x6c3 +#define XK_Cyrillic_de 0x6c4 +#define XK_Cyrillic_ie 0x6c5 +#define XK_Cyrillic_ef 0x6c6 +#define XK_Cyrillic_ghe 0x6c7 +#define XK_Cyrillic_ha 0x6c8 +#define XK_Cyrillic_i 0x6c9 +#define XK_Cyrillic_shorti 0x6ca +#define XK_Cyrillic_ka 0x6cb +#define XK_Cyrillic_el 0x6cc +#define XK_Cyrillic_em 0x6cd +#define XK_Cyrillic_en 0x6ce +#define XK_Cyrillic_o 0x6cf +#define XK_Cyrillic_pe 0x6d0 +#define XK_Cyrillic_ya 0x6d1 +#define XK_Cyrillic_er 0x6d2 +#define XK_Cyrillic_es 0x6d3 +#define XK_Cyrillic_te 0x6d4 +#define XK_Cyrillic_u 0x6d5 +#define XK_Cyrillic_zhe 0x6d6 +#define XK_Cyrillic_ve 0x6d7 +#define XK_Cyrillic_softsign 0x6d8 +#define XK_Cyrillic_yeru 0x6d9 +#define XK_Cyrillic_ze 0x6da +#define XK_Cyrillic_sha 0x6db +#define XK_Cyrillic_e 0x6dc +#define XK_Cyrillic_shcha 0x6dd +#define XK_Cyrillic_che 0x6de +#define XK_Cyrillic_hardsign 0x6df +#define XK_Cyrillic_YU 0x6e0 +#define XK_Cyrillic_A 0x6e1 +#define XK_Cyrillic_BE 0x6e2 +#define XK_Cyrillic_TSE 0x6e3 +#define XK_Cyrillic_DE 0x6e4 +#define XK_Cyrillic_IE 0x6e5 +#define XK_Cyrillic_EF 0x6e6 +#define XK_Cyrillic_GHE 0x6e7 +#define XK_Cyrillic_HA 0x6e8 +#define XK_Cyrillic_I 0x6e9 +#define XK_Cyrillic_SHORTI 0x6ea +#define XK_Cyrillic_KA 0x6eb +#define XK_Cyrillic_EL 0x6ec +#define XK_Cyrillic_EM 0x6ed +#define XK_Cyrillic_EN 0x6ee +#define XK_Cyrillic_O 0x6ef +#define XK_Cyrillic_PE 0x6f0 +#define XK_Cyrillic_YA 0x6f1 +#define XK_Cyrillic_ER 0x6f2 +#define XK_Cyrillic_ES 0x6f3 +#define XK_Cyrillic_TE 0x6f4 +#define XK_Cyrillic_U 0x6f5 +#define XK_Cyrillic_ZHE 0x6f6 +#define XK_Cyrillic_VE 0x6f7 +#define XK_Cyrillic_SOFTSIGN 0x6f8 +#define XK_Cyrillic_YERU 0x6f9 +#define XK_Cyrillic_ZE 0x6fa +#define XK_Cyrillic_SHA 0x6fb +#define XK_Cyrillic_E 0x6fc +#define XK_Cyrillic_SHCHA 0x6fd +#define XK_Cyrillic_CHE 0x6fe +#define XK_Cyrillic_HARDSIGN 0x6ff +#endif /* XK_CYRILLIC */ + +/* + * Greek + * Byte 3 = 7 + */ + +#ifdef XK_GREEK +#define XK_Greek_ALPHAaccent 0x7a1 +#define XK_Greek_EPSILONaccent 0x7a2 +#define XK_Greek_ETAaccent 0x7a3 +#define XK_Greek_IOTAaccent 0x7a4 +#define XK_Greek_IOTAdieresis 0x7a5 +#define XK_Greek_OMICRONaccent 0x7a7 +#define XK_Greek_UPSILONaccent 0x7a8 +#define XK_Greek_UPSILONdieresis 0x7a9 +#define XK_Greek_OMEGAaccent 0x7ab +#define XK_Greek_accentdieresis 0x7ae +#define XK_Greek_horizbar 0x7af +#define XK_Greek_alphaaccent 0x7b1 +#define XK_Greek_epsilonaccent 0x7b2 +#define XK_Greek_etaaccent 0x7b3 +#define XK_Greek_iotaaccent 0x7b4 +#define XK_Greek_iotadieresis 0x7b5 +#define XK_Greek_iotaaccentdieresis 0x7b6 +#define XK_Greek_omicronaccent 0x7b7 +#define XK_Greek_upsilonaccent 0x7b8 +#define XK_Greek_upsilondieresis 0x7b9 +#define XK_Greek_upsilonaccentdieresis 0x7ba +#define XK_Greek_omegaaccent 0x7bb +#define XK_Greek_ALPHA 0x7c1 +#define XK_Greek_BETA 0x7c2 +#define XK_Greek_GAMMA 0x7c3 +#define XK_Greek_DELTA 0x7c4 +#define XK_Greek_EPSILON 0x7c5 +#define XK_Greek_ZETA 0x7c6 +#define XK_Greek_ETA 0x7c7 +#define XK_Greek_THETA 0x7c8 +#define XK_Greek_IOTA 0x7c9 +#define XK_Greek_KAPPA 0x7ca +#define XK_Greek_LAMDA 0x7cb +#define XK_Greek_LAMBDA 0x7cb +#define XK_Greek_MU 0x7cc +#define XK_Greek_NU 0x7cd +#define XK_Greek_XI 0x7ce +#define XK_Greek_OMICRON 0x7cf +#define XK_Greek_PI 0x7d0 +#define XK_Greek_RHO 0x7d1 +#define XK_Greek_SIGMA 0x7d2 +#define XK_Greek_TAU 0x7d4 +#define XK_Greek_UPSILON 0x7d5 +#define XK_Greek_PHI 0x7d6 +#define XK_Greek_CHI 0x7d7 +#define XK_Greek_PSI 0x7d8 +#define XK_Greek_OMEGA 0x7d9 +#define XK_Greek_alpha 0x7e1 +#define XK_Greek_beta 0x7e2 +#define XK_Greek_gamma 0x7e3 +#define XK_Greek_delta 0x7e4 +#define XK_Greek_epsilon 0x7e5 +#define XK_Greek_zeta 0x7e6 +#define XK_Greek_eta 0x7e7 +#define XK_Greek_theta 0x7e8 +#define XK_Greek_iota 0x7e9 +#define XK_Greek_kappa 0x7ea +#define XK_Greek_lamda 0x7eb +#define XK_Greek_lambda 0x7eb +#define XK_Greek_mu 0x7ec +#define XK_Greek_nu 0x7ed +#define XK_Greek_xi 0x7ee +#define XK_Greek_omicron 0x7ef +#define XK_Greek_pi 0x7f0 +#define XK_Greek_rho 0x7f1 +#define XK_Greek_sigma 0x7f2 +#define XK_Greek_finalsmallsigma 0x7f3 +#define XK_Greek_tau 0x7f4 +#define XK_Greek_upsilon 0x7f5 +#define XK_Greek_phi 0x7f6 +#define XK_Greek_chi 0x7f7 +#define XK_Greek_psi 0x7f8 +#define XK_Greek_omega 0x7f9 +#define XK_Greek_switch 0xFF7E /* Alias for mode_switch */ +#endif /* XK_GREEK */ + +/* + * Technical + * Byte 3 = 8 + */ + +#ifdef XK_TECHNICAL +#define XK_leftradical 0x8a1 +#define XK_topleftradical 0x8a2 +#define XK_horizconnector 0x8a3 +#define XK_topintegral 0x8a4 +#define XK_botintegral 0x8a5 +#define XK_vertconnector 0x8a6 +#define XK_topleftsqbracket 0x8a7 +#define XK_botleftsqbracket 0x8a8 +#define XK_toprightsqbracket 0x8a9 +#define XK_botrightsqbracket 0x8aa +#define XK_topleftparens 0x8ab +#define XK_botleftparens 0x8ac +#define XK_toprightparens 0x8ad +#define XK_botrightparens 0x8ae +#define XK_leftmiddlecurlybrace 0x8af +#define XK_rightmiddlecurlybrace 0x8b0 +#define XK_topleftsummation 0x8b1 +#define XK_botleftsummation 0x8b2 +#define XK_topvertsummationconnector 0x8b3 +#define XK_botvertsummationconnector 0x8b4 +#define XK_toprightsummation 0x8b5 +#define XK_botrightsummation 0x8b6 +#define XK_rightmiddlesummation 0x8b7 +#define XK_lessthanequal 0x8bc +#define XK_notequal 0x8bd +#define XK_greaterthanequal 0x8be +#define XK_integral 0x8bf +#define XK_therefore 0x8c0 +#define XK_variation 0x8c1 +#define XK_infinity 0x8c2 +#define XK_nabla 0x8c5 +#define XK_approximate 0x8c8 +#define XK_similarequal 0x8c9 +#define XK_ifonlyif 0x8cd +#define XK_implies 0x8ce +#define XK_identical 0x8cf +#define XK_radical 0x8d6 +#define XK_includedin 0x8da +#define XK_includes 0x8db +#define XK_intersection 0x8dc +#define XK_union 0x8dd +#define XK_logicaland 0x8de +#define XK_logicalor 0x8df +#define XK_partialderivative 0x8ef +#define XK_function 0x8f6 +#define XK_leftarrow 0x8fb +#define XK_uparrow 0x8fc +#define XK_rightarrow 0x8fd +#define XK_downarrow 0x8fe +#endif /* XK_TECHNICAL */ + +/* + * Special + * Byte 3 = 9 + */ + +#ifdef XK_SPECIAL +#define XK_blank 0x9df +#define XK_soliddiamond 0x9e0 +#define XK_checkerboard 0x9e1 +#define XK_ht 0x9e2 +#define XK_ff 0x9e3 +#define XK_cr 0x9e4 +#define XK_lf 0x9e5 +#define XK_nl 0x9e8 +#define XK_vt 0x9e9 +#define XK_lowrightcorner 0x9ea +#define XK_uprightcorner 0x9eb +#define XK_upleftcorner 0x9ec +#define XK_lowleftcorner 0x9ed +#define XK_crossinglines 0x9ee +#define XK_horizlinescan1 0x9ef +#define XK_horizlinescan3 0x9f0 +#define XK_horizlinescan5 0x9f1 +#define XK_horizlinescan7 0x9f2 +#define XK_horizlinescan9 0x9f3 +#define XK_leftt 0x9f4 +#define XK_rightt 0x9f5 +#define XK_bott 0x9f6 +#define XK_topt 0x9f7 +#define XK_vertbar 0x9f8 +#endif /* XK_SPECIAL */ + +/* + * Publishing + * Byte 3 = a + */ + +#ifdef XK_PUBLISHING +#define XK_emspace 0xaa1 +#define XK_enspace 0xaa2 +#define XK_em3space 0xaa3 +#define XK_em4space 0xaa4 +#define XK_digitspace 0xaa5 +#define XK_punctspace 0xaa6 +#define XK_thinspace 0xaa7 +#define XK_hairspace 0xaa8 +#define XK_emdash 0xaa9 +#define XK_endash 0xaaa +#define XK_signifblank 0xaac +#define XK_ellipsis 0xaae +#define XK_doubbaselinedot 0xaaf +#define XK_onethird 0xab0 +#define XK_twothirds 0xab1 +#define XK_onefifth 0xab2 +#define XK_twofifths 0xab3 +#define XK_threefifths 0xab4 +#define XK_fourfifths 0xab5 +#define XK_onesixth 0xab6 +#define XK_fivesixths 0xab7 +#define XK_careof 0xab8 +#define XK_figdash 0xabb +#define XK_leftanglebracket 0xabc +#define XK_decimalpoint 0xabd +#define XK_rightanglebracket 0xabe +#define XK_marker 0xabf +#define XK_oneeighth 0xac3 +#define XK_threeeighths 0xac4 +#define XK_fiveeighths 0xac5 +#define XK_seveneighths 0xac6 +#define XK_trademark 0xac9 +#define XK_signaturemark 0xaca +#define XK_trademarkincircle 0xacb +#define XK_leftopentriangle 0xacc +#define XK_rightopentriangle 0xacd +#define XK_emopencircle 0xace +#define XK_emopenrectangle 0xacf +#define XK_leftsinglequotemark 0xad0 +#define XK_rightsinglequotemark 0xad1 +#define XK_leftdoublequotemark 0xad2 +#define XK_rightdoublequotemark 0xad3 +#define XK_prescription 0xad4 +#define XK_minutes 0xad6 +#define XK_seconds 0xad7 +#define XK_latincross 0xad9 +#define XK_hexagram 0xada +#define XK_filledrectbullet 0xadb +#define XK_filledlefttribullet 0xadc +#define XK_filledrighttribullet 0xadd +#define XK_emfilledcircle 0xade +#define XK_emfilledrect 0xadf +#define XK_enopencircbullet 0xae0 +#define XK_enopensquarebullet 0xae1 +#define XK_openrectbullet 0xae2 +#define XK_opentribulletup 0xae3 +#define XK_opentribulletdown 0xae4 +#define XK_openstar 0xae5 +#define XK_enfilledcircbullet 0xae6 +#define XK_enfilledsqbullet 0xae7 +#define XK_filledtribulletup 0xae8 +#define XK_filledtribulletdown 0xae9 +#define XK_leftpointer 0xaea +#define XK_rightpointer 0xaeb +#define XK_club 0xaec +#define XK_diamond 0xaed +#define XK_heart 0xaee +#define XK_maltesecross 0xaf0 +#define XK_dagger 0xaf1 +#define XK_doubledagger 0xaf2 +#define XK_checkmark 0xaf3 +#define XK_ballotcross 0xaf4 +#define XK_musicalsharp 0xaf5 +#define XK_musicalflat 0xaf6 +#define XK_malesymbol 0xaf7 +#define XK_femalesymbol 0xaf8 +#define XK_telephone 0xaf9 +#define XK_telephonerecorder 0xafa +#define XK_phonographcopyright 0xafb +#define XK_caret 0xafc +#define XK_singlelowquotemark 0xafd +#define XK_doublelowquotemark 0xafe +#define XK_cursor 0xaff +#endif /* XK_PUBLISHING */ + +/* + * APL + * Byte 3 = b + */ + +#ifdef XK_APL +#define XK_leftcaret 0xba3 +#define XK_rightcaret 0xba6 +#define XK_downcaret 0xba8 +#define XK_upcaret 0xba9 +#define XK_overbar 0xbc0 +#define XK_downtack 0xbc2 +#define XK_upshoe 0xbc3 +#define XK_downstile 0xbc4 +#define XK_underbar 0xbc6 +#define XK_jot 0xbca +#define XK_quad 0xbcc +#define XK_uptack 0xbce +#define XK_circle 0xbcf +#define XK_upstile 0xbd3 +#define XK_downshoe 0xbd6 +#define XK_rightshoe 0xbd8 +#define XK_leftshoe 0xbda +#define XK_lefttack 0xbdc +#define XK_righttack 0xbfc +#endif /* XK_APL */ + +/* + * Hebrew + * Byte 3 = c + */ + +#ifdef XK_HEBREW +#define XK_hebrew_doublelowline 0xcdf +#define XK_hebrew_aleph 0xce0 +#define XK_hebrew_bet 0xce1 +#define XK_hebrew_beth 0xce1 /* deprecated */ +#define XK_hebrew_gimel 0xce2 +#define XK_hebrew_gimmel 0xce2 /* deprecated */ +#define XK_hebrew_dalet 0xce3 +#define XK_hebrew_daleth 0xce3 /* deprecated */ +#define XK_hebrew_he 0xce4 +#define XK_hebrew_waw 0xce5 +#define XK_hebrew_zain 0xce6 +#define XK_hebrew_zayin 0xce6 /* deprecated */ +#define XK_hebrew_chet 0xce7 +#define XK_hebrew_het 0xce7 /* deprecated */ +#define XK_hebrew_tet 0xce8 +#define XK_hebrew_teth 0xce8 /* deprecated */ +#define XK_hebrew_yod 0xce9 +#define XK_hebrew_finalkaph 0xcea +#define XK_hebrew_kaph 0xceb +#define XK_hebrew_lamed 0xcec +#define XK_hebrew_finalmem 0xced +#define XK_hebrew_mem 0xcee +#define XK_hebrew_finalnun 0xcef +#define XK_hebrew_nun 0xcf0 +#define XK_hebrew_samech 0xcf1 +#define XK_hebrew_samekh 0xcf1 /* deprecated */ +#define XK_hebrew_ayin 0xcf2 +#define XK_hebrew_finalpe 0xcf3 +#define XK_hebrew_pe 0xcf4 +#define XK_hebrew_finalzade 0xcf5 +#define XK_hebrew_finalzadi 0xcf5 /* deprecated */ +#define XK_hebrew_zade 0xcf6 +#define XK_hebrew_zadi 0xcf6 /* deprecated */ +#define XK_hebrew_qoph 0xcf7 +#define XK_hebrew_kuf 0xcf7 /* deprecated */ +#define XK_hebrew_resh 0xcf8 +#define XK_hebrew_shin 0xcf9 +#define XK_hebrew_taw 0xcfa +#define XK_hebrew_taf 0xcfa /* deprecated */ +#define XK_Hebrew_switch 0xFF7E /* Alias for mode_switch */ +#endif /* XK_HEBREW */ + +/* + * Thai + * Byte 3 = d + */ + +#ifdef XK_THAI +#define XK_Thai_kokai 0xda1 +#define XK_Thai_khokhai 0xda2 +#define XK_Thai_khokhuat 0xda3 +#define XK_Thai_khokhwai 0xda4 +#define XK_Thai_khokhon 0xda5 +#define XK_Thai_khorakhang 0xda6 +#define XK_Thai_ngongu 0xda7 +#define XK_Thai_chochan 0xda8 +#define XK_Thai_choching 0xda9 +#define XK_Thai_chochang 0xdaa +#define XK_Thai_soso 0xdab +#define XK_Thai_chochoe 0xdac +#define XK_Thai_yoying 0xdad +#define XK_Thai_dochada 0xdae +#define XK_Thai_topatak 0xdaf +#define XK_Thai_thothan 0xdb0 +#define XK_Thai_thonangmontho 0xdb1 +#define XK_Thai_thophuthao 0xdb2 +#define XK_Thai_nonen 0xdb3 +#define XK_Thai_dodek 0xdb4 +#define XK_Thai_totao 0xdb5 +#define XK_Thai_thothung 0xdb6 +#define XK_Thai_thothahan 0xdb7 +#define XK_Thai_thothong 0xdb8 +#define XK_Thai_nonu 0xdb9 +#define XK_Thai_bobaimai 0xdba +#define XK_Thai_popla 0xdbb +#define XK_Thai_phophung 0xdbc +#define XK_Thai_fofa 0xdbd +#define XK_Thai_phophan 0xdbe +#define XK_Thai_fofan 0xdbf +#define XK_Thai_phosamphao 0xdc0 +#define XK_Thai_moma 0xdc1 +#define XK_Thai_yoyak 0xdc2 +#define XK_Thai_rorua 0xdc3 +#define XK_Thai_ru 0xdc4 +#define XK_Thai_loling 0xdc5 +#define XK_Thai_lu 0xdc6 +#define XK_Thai_wowaen 0xdc7 +#define XK_Thai_sosala 0xdc8 +#define XK_Thai_sorusi 0xdc9 +#define XK_Thai_sosua 0xdca +#define XK_Thai_hohip 0xdcb +#define XK_Thai_lochula 0xdcc +#define XK_Thai_oang 0xdcd +#define XK_Thai_honokhuk 0xdce +#define XK_Thai_paiyannoi 0xdcf +#define XK_Thai_saraa 0xdd0 +#define XK_Thai_maihanakat 0xdd1 +#define XK_Thai_saraaa 0xdd2 +#define XK_Thai_saraam 0xdd3 +#define XK_Thai_sarai 0xdd4 +#define XK_Thai_saraii 0xdd5 +#define XK_Thai_saraue 0xdd6 +#define XK_Thai_sarauee 0xdd7 +#define XK_Thai_sarau 0xdd8 +#define XK_Thai_sarauu 0xdd9 +#define XK_Thai_phinthu 0xdda +#define XK_Thai_maihanakat_maitho 0xdde +#define XK_Thai_baht 0xddf +#define XK_Thai_sarae 0xde0 +#define XK_Thai_saraae 0xde1 +#define XK_Thai_sarao 0xde2 +#define XK_Thai_saraaimaimuan 0xde3 +#define XK_Thai_saraaimaimalai 0xde4 +#define XK_Thai_lakkhangyao 0xde5 +#define XK_Thai_maiyamok 0xde6 +#define XK_Thai_maitaikhu 0xde7 +#define XK_Thai_maiek 0xde8 +#define XK_Thai_maitho 0xde9 +#define XK_Thai_maitri 0xdea +#define XK_Thai_maichattawa 0xdeb +#define XK_Thai_thanthakhat 0xdec +#define XK_Thai_nikhahit 0xded +#define XK_Thai_leksun 0xdf0 +#define XK_Thai_leknung 0xdf1 +#define XK_Thai_leksong 0xdf2 +#define XK_Thai_leksam 0xdf3 +#define XK_Thai_leksi 0xdf4 +#define XK_Thai_lekha 0xdf5 +#define XK_Thai_lekhok 0xdf6 +#define XK_Thai_lekchet 0xdf7 +#define XK_Thai_lekpaet 0xdf8 +#define XK_Thai_lekkao 0xdf9 +#endif /* XK_THAI */ + +/* + * Korean + * Byte 3 = e + */ + +#ifdef XK_KOREAN + +#define XK_Hangul 0xff31 /* Hangul start/stop(toggle) */ +#define XK_Hangul_Start 0xff32 /* Hangul start */ +#define XK_Hangul_End 0xff33 /* Hangul end, English start */ +#define XK_Hangul_Hanja 0xff34 /* Start Hangul->Hanja Conversion */ +#define XK_Hangul_Jamo 0xff35 /* Hangul Jamo mode */ +#define XK_Hangul_Romaja 0xff36 /* Hangul Romaja mode */ +#define XK_Hangul_Codeinput 0xff37 /* Hangul code input mode */ +#define XK_Hangul_Jeonja 0xff38 /* Jeonja mode */ +#define XK_Hangul_Banja 0xff39 /* Banja mode */ +#define XK_Hangul_PreHanja 0xff3a /* Pre Hanja conversion */ +#define XK_Hangul_PostHanja 0xff3b /* Post Hanja conversion */ +#define XK_Hangul_SingleCandidate 0xff3c /* Single candidate */ +#define XK_Hangul_MultipleCandidate 0xff3d /* Multiple candidate */ +#define XK_Hangul_PreviousCandidate 0xff3e /* Previous candidate */ +#define XK_Hangul_Special 0xff3f /* Special symbols */ +#define XK_Hangul_switch 0xFF7E /* Alias for mode_switch */ + +/* Hangul Consonant Characters */ +#define XK_Hangul_Kiyeog 0xea1 +#define XK_Hangul_SsangKiyeog 0xea2 +#define XK_Hangul_KiyeogSios 0xea3 +#define XK_Hangul_Nieun 0xea4 +#define XK_Hangul_NieunJieuj 0xea5 +#define XK_Hangul_NieunHieuh 0xea6 +#define XK_Hangul_Dikeud 0xea7 +#define XK_Hangul_SsangDikeud 0xea8 +#define XK_Hangul_Rieul 0xea9 +#define XK_Hangul_RieulKiyeog 0xeaa +#define XK_Hangul_RieulMieum 0xeab +#define XK_Hangul_RieulPieub 0xeac +#define XK_Hangul_RieulSios 0xead +#define XK_Hangul_RieulTieut 0xeae +#define XK_Hangul_RieulPhieuf 0xeaf +#define XK_Hangul_RieulHieuh 0xeb0 +#define XK_Hangul_Mieum 0xeb1 +#define XK_Hangul_Pieub 0xeb2 +#define XK_Hangul_SsangPieub 0xeb3 +#define XK_Hangul_PieubSios 0xeb4 +#define XK_Hangul_Sios 0xeb5 +#define XK_Hangul_SsangSios 0xeb6 +#define XK_Hangul_Ieung 0xeb7 +#define XK_Hangul_Jieuj 0xeb8 +#define XK_Hangul_SsangJieuj 0xeb9 +#define XK_Hangul_Cieuc 0xeba +#define XK_Hangul_Khieuq 0xebb +#define XK_Hangul_Tieut 0xebc +#define XK_Hangul_Phieuf 0xebd +#define XK_Hangul_Hieuh 0xebe + +/* Hangul Vowel Characters */ +#define XK_Hangul_A 0xebf +#define XK_Hangul_AE 0xec0 +#define XK_Hangul_YA 0xec1 +#define XK_Hangul_YAE 0xec2 +#define XK_Hangul_EO 0xec3 +#define XK_Hangul_E 0xec4 +#define XK_Hangul_YEO 0xec5 +#define XK_Hangul_YE 0xec6 +#define XK_Hangul_O 0xec7 +#define XK_Hangul_WA 0xec8 +#define XK_Hangul_WAE 0xec9 +#define XK_Hangul_OE 0xeca +#define XK_Hangul_YO 0xecb +#define XK_Hangul_U 0xecc +#define XK_Hangul_WEO 0xecd +#define XK_Hangul_WE 0xece +#define XK_Hangul_WI 0xecf +#define XK_Hangul_YU 0xed0 +#define XK_Hangul_EU 0xed1 +#define XK_Hangul_YI 0xed2 +#define XK_Hangul_I 0xed3 + +/* Hangul syllable-final (JongSeong) Characters */ +#define XK_Hangul_J_Kiyeog 0xed4 +#define XK_Hangul_J_SsangKiyeog 0xed5 +#define XK_Hangul_J_KiyeogSios 0xed6 +#define XK_Hangul_J_Nieun 0xed7 +#define XK_Hangul_J_NieunJieuj 0xed8 +#define XK_Hangul_J_NieunHieuh 0xed9 +#define XK_Hangul_J_Dikeud 0xeda +#define XK_Hangul_J_Rieul 0xedb +#define XK_Hangul_J_RieulKiyeog 0xedc +#define XK_Hangul_J_RieulMieum 0xedd +#define XK_Hangul_J_RieulPieub 0xede +#define XK_Hangul_J_RieulSios 0xedf +#define XK_Hangul_J_RieulTieut 0xee0 +#define XK_Hangul_J_RieulPhieuf 0xee1 +#define XK_Hangul_J_RieulHieuh 0xee2 +#define XK_Hangul_J_Mieum 0xee3 +#define XK_Hangul_J_Pieub 0xee4 +#define XK_Hangul_J_PieubSios 0xee5 +#define XK_Hangul_J_Sios 0xee6 +#define XK_Hangul_J_SsangSios 0xee7 +#define XK_Hangul_J_Ieung 0xee8 +#define XK_Hangul_J_Jieuj 0xee9 +#define XK_Hangul_J_Cieuc 0xeea +#define XK_Hangul_J_Khieuq 0xeeb +#define XK_Hangul_J_Tieut 0xeec +#define XK_Hangul_J_Phieuf 0xeed +#define XK_Hangul_J_Hieuh 0xeee + +/* Ancient Hangul Consonant Characters */ +#define XK_Hangul_RieulYeorinHieuh 0xeef +#define XK_Hangul_SunkyeongeumMieum 0xef0 +#define XK_Hangul_SunkyeongeumPieub 0xef1 +#define XK_Hangul_PanSios 0xef2 +#define XK_Hangul_KkogjiDalrinIeung 0xef3 +#define XK_Hangul_SunkyeongeumPhieuf 0xef4 +#define XK_Hangul_YeorinHieuh 0xef5 + +/* Ancient Hangul Vowel Characters */ +#define XK_Hangul_AraeA 0xef6 +#define XK_Hangul_AraeAE 0xef7 + +/* Ancient Hangul syllable-final (JongSeong) Characters */ +#define XK_Hangul_J_PanSios 0xef8 +#define XK_Hangul_J_KkogjiDalrinIeung 0xef9 +#define XK_Hangul_J_YeorinHieuh 0xefa + +/* Korean currency symbol */ +#define XK_Korean_Won 0xeff + +#endif /* XK_KOREAN */ + +/* Euro currency symbol */ +#define XK_EuroSign 0x20ac + +#endif diff --git a/rfb/rfb.h b/rfb/rfb.h new file mode 100644 index 0000000..4f275fc --- /dev/null +++ b/rfb/rfb.h @@ -0,0 +1,1297 @@ +#ifndef RFB_H +#define RFB_H +/** + * @defgroup libvncserver_api LibVNCServer API Reference + * @{ + */ + +/** + * @file rfb.h + */ + +/* + * Copyright (C) 2005 Rohit Kumar , + * Johannes E. Schindelin + * Copyright (C) 2002 RealVNC Ltd. + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#if(defined __cplusplus) +extern "C" +{ +#endif + +#include +#include +#include +#include + +#if defined(ANDROID) || defined(LIBVNCSERVER_HAVE_ANDROID) +#include +#include +#endif + +#ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H +#include +#endif + +#ifdef WIN32 +typedef UINT32 in_addr_t; +#include +#ifdef LIBVNCSERVER_HAVE_WS2TCPIP_H +#undef socklen_t +#include +#endif +#ifdef _MSC_VER +#pragma warning(disable:4996) +#endif +#endif + +#include + +/* if you use pthreads, but don't define LIBVNCSERVER_HAVE_LIBPTHREAD, the structs + get all mixed up. So this gives a linker error reminding you to compile + the library and your application (at least the parts including rfb.h) + with the same support for pthreads. */ +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD +#ifdef LIBVNCSERVER_HAVE_LIBZ +#define rfbInitServer rfbInitServerWithPthreadsAndZRLE +#else +#define rfbInitServer rfbInitServerWithPthreadsButWithoutZRLE +#endif +#else +#ifdef LIBVNCSERVER_HAVE_LIBZ +#define rfbInitServer rfbInitServerWithoutPthreadsButWithZRLE +#else +#define rfbInitServer rfbInitServerWithoutPthreadsAndZRLE +#endif +#endif + +struct _rfbClientRec; +struct _rfbScreenInfo; +struct rfbCursor; + +enum rfbNewClientAction { + RFB_CLIENT_ACCEPT, + RFB_CLIENT_ON_HOLD, + RFB_CLIENT_REFUSE +}; + +enum rfbSocketState { + RFB_SOCKET_INIT, + RFB_SOCKET_READY, + RFB_SOCKET_SHUTDOWN +}; + +typedef void (*rfbKbdAddEventProcPtr) (rfbBool down, rfbKeySym keySym, struct _rfbClientRec* cl); +typedef void (*rfbKbdReleaseAllKeysProcPtr) (struct _rfbClientRec* cl); +typedef void (*rfbPtrAddEventProcPtr) (int buttonMask, int x, int y, struct _rfbClientRec* cl); +typedef void (*rfbSetXCutTextProcPtr) (char* str,int len, struct _rfbClientRec* cl); +#ifdef LIBVNCSERVER_HAVE_LIBZ +typedef void (*rfbSetXCutTextUTF8ProcPtr) (char* str,int len, struct _rfbClientRec* cl); +#endif +typedef struct rfbCursor* (*rfbGetCursorProcPtr) (struct _rfbClientRec* pScreen); +typedef rfbBool (*rfbSetTranslateFunctionProcPtr)(struct _rfbClientRec* cl); +typedef rfbBool (*rfbPasswordCheckProcPtr)(struct _rfbClientRec* cl,const char* encryptedPassWord,int len); +typedef enum rfbNewClientAction (*rfbNewClientHookPtr)(struct _rfbClientRec* cl); +typedef void (*rfbDisplayHookPtr)(struct _rfbClientRec* cl); +typedef void (*rfbDisplayFinishedHookPtr)(struct _rfbClientRec* cl, int result); +/** support the capability to view the caps/num/scroll states of the X server */ +typedef int (*rfbGetKeyboardLedStateHookPtr)(struct _rfbScreenInfo* screen); +typedef rfbBool (*rfbXvpHookPtr)(struct _rfbClientRec* cl, uint8_t, uint8_t); +typedef int (*rfbSetDesktopSizeHookPtr)(int width, int height, int numScreens, struct rfbExtDesktopScreen* extDesktopScreens, struct _rfbClientRec* cl); +typedef int (*rfbNumberOfExtDesktopScreensPtr)(struct _rfbClientRec* cl); +typedef rfbBool (*rfbGetExtDesktopScreenPtr)(int seqnumber, struct rfbExtDesktopScreen *extDesktopScreen, struct _rfbClientRec* cl); +/** + * If x==1 and y==1 then set the whole display + * else find the window underneath x and y and set the framebuffer to the dimensions + * of that window + */ +typedef void (*rfbSetSingleWindowProcPtr) (struct _rfbClientRec* cl, int x, int y); +/** + * Status determines if the X11 server permits input from the local user + * status==0 or 1 + */ +typedef void (*rfbSetServerInputProcPtr) (struct _rfbClientRec* cl, int status); +/** + * Permit the server to allow or deny filetransfers. This is defaulted to deny + * It is called when a client initiates a connection to determine if it is permitted. + */ +typedef int (*rfbFileTransferPermitted) (struct _rfbClientRec* cl); +/** Handle the textchat messages */ +typedef void (*rfbSetTextChat) (struct _rfbClientRec* cl, int length, char *string); + +typedef struct { + uint32_t count; + rfbBool is16; /**< is the data format short? */ + union { + uint8_t* bytes; + uint16_t* shorts; + } data; /**< there have to be count*3 entries */ +} rfbColourMap; + +/** + * Security handling (RFB protocol version 3.7) + */ + +typedef struct _rfbSecurity { + uint8_t type; + void (*handler)(struct _rfbClientRec* cl); + struct _rfbSecurity* next; +} rfbSecurityHandler; + +/** + * Protocol extension handling. + */ + +typedef struct _rfbProtocolExtension { + /** returns FALSE if extension should be deactivated for client. + if newClient == NULL, it is always deactivated. */ + rfbBool (*newClient)(struct _rfbClientRec* client, void** data); + /** returns FALSE if extension should be deactivated for client. + if init == NULL, it stays activated. */ + rfbBool (*init)(struct _rfbClientRec* client, void* data); + /** if pseudoEncodings is not NULL, it contains a 0 terminated + list of the pseudo encodings handled by this extension. */ + int *pseudoEncodings; + /** returns TRUE if that pseudo encoding is handled by the extension. + encodingNumber==0 means "reset encodings". */ + rfbBool (*enablePseudoEncoding)(struct _rfbClientRec* client, + void** data, int encodingNumber); + /** returns TRUE if message was handled */ + rfbBool (*handleMessage)(struct _rfbClientRec* client, + void* data, + const rfbClientToServerMsg* message); + void (*close)(struct _rfbClientRec* client, void* data); + void (*usage)(void); + /** processArguments returns the number of handled arguments */ + int (*processArgument)(int argc, char *argv[]); + struct _rfbProtocolExtension* next; +} rfbProtocolExtension; + +typedef struct _rfbExtensionData { + rfbProtocolExtension* extension; + void* data; + struct _rfbExtensionData* next; +} rfbExtensionData; + +/** + * Per-screen (framebuffer) structure. There can be as many as you wish, + * each serving different clients. However, you have to call + * rfbProcessEvents for each of these. + */ + +typedef struct _rfbScreenInfo +{ + /** this structure has children that are scaled versions of this screen */ + struct _rfbScreenInfo *scaledScreenNext; + int scaledScreenRefCount; + + int width; + int paddedWidthInBytes; + int height; + int depth; + int bitsPerPixel; + int sizeInBytes; + + rfbPixel blackPixel; + rfbPixel whitePixel; + + /** + * some screen specific data can be put into a struct where screenData + * points to. You need this if you have more than one screen at the + * same time while using the same functions. + */ + void* screenData; + + /* additions by libvncserver */ + + rfbPixelFormat serverFormat; + rfbColourMap colourMap; /**< set this if rfbServerFormat.trueColour==FALSE */ + const char* desktopName; + char thisHost[255]; + + rfbBool autoPort; + int port; + rfbSocket listenSock; + int maxSock; + int maxFd; +#ifdef WIN32 + struct fd_set allFds; +#else + fd_set allFds; +#endif + + enum rfbSocketState socketState; + rfbSocket inetdSock; + rfbBool inetdInitDone; + + int udpPort; + rfbSocket udpSock; + struct _rfbClientRec* udpClient; + rfbBool udpSockConnected; + struct sockaddr_in udpRemoteAddr; + + int maxClientWait; + + /* http stuff */ + rfbBool httpInitDone; + rfbBool httpEnableProxyConnect; + int httpPort; + char* httpDir; + rfbSocket httpListenSock; + rfbSocket httpSock; + + rfbPasswordCheckProcPtr passwordCheck; + void* authPasswdData; + /** If rfbAuthPasswdData is given a list, this is the first + view only password. */ + int authPasswdFirstViewOnly; + + /** send only this many rectangles in one update */ + int maxRectsPerUpdate; + /** this is the amount of milliseconds to wait at least before sending + * an update. */ + int deferUpdateTime; +#ifdef TODELETE + char* screen; +#endif + rfbBool alwaysShared; + rfbBool neverShared; + rfbBool dontDisconnect; + struct _rfbClientRec* clientHead; + struct _rfbClientRec* pointerClient; /**< "Mutex" for pointer events */ + + + /* cursor */ + int cursorX, cursorY,underCursorBufferLen; + char* underCursorBuffer; + rfbBool dontConvertRichCursorToXCursor; + struct rfbCursor* cursor; + + /** + * the frameBuffer has to be supplied by the serving process. + * The buffer will not be freed by + */ + char* frameBuffer; + rfbKbdAddEventProcPtr kbdAddEvent; + rfbKbdReleaseAllKeysProcPtr kbdReleaseAllKeys; + rfbPtrAddEventProcPtr ptrAddEvent; + rfbSetXCutTextProcPtr setXCutText; +#ifdef LIBVNCSERVER_HAVE_LIBZ + rfbSetXCutTextUTF8ProcPtr setXCutTextUTF8; +#endif + rfbGetCursorProcPtr getCursorPtr; + rfbSetTranslateFunctionProcPtr setTranslateFunction; + rfbSetSingleWindowProcPtr setSingleWindow; + rfbSetServerInputProcPtr setServerInput; + rfbFileTransferPermitted getFileTransferPermission; + rfbSetTextChat setTextChat; + + /** newClientHook is called just after a new client is created */ + rfbNewClientHookPtr newClientHook; + /** displayHook is called just before a frame buffer update */ + rfbDisplayHookPtr displayHook; + + /** These hooks are called to pass keyboard state back to the client */ + rfbGetKeyboardLedStateHookPtr getKeyboardLedStateHook; + +#if defined(LIBVNCSERVER_HAVE_LIBPTHREAD) || defined(LIBVNCSERVER_HAVE_WIN32THREADS) + MUTEX(cursorMutex); + rfbBool backgroundLoop; +#endif + + /** if TRUE, an ignoring signal handler is installed for SIGPIPE */ + rfbBool ignoreSIGPIPE; + + /** if not zero, only a slice of this height is processed every time + * an update should be sent. This should make working on a slow + * link more interactive. */ + int progressiveSliceHeight; + + in_addr_t listenInterface; + int deferPtrUpdateTime; + + /** handle as many input events as possible (default off) */ + rfbBool handleEventsEagerly; + + /** rfbEncodingServerIdentity */ + char *versionString; + + /** What does the server tell the new clients which version it supports */ + int protocolMajorVersion; + int protocolMinorVersion; + + /** command line authorization of file transfers */ + rfbBool permitFileTransfer; + + /** displayFinishedHook is called just after a frame buffer update */ + rfbDisplayFinishedHookPtr displayFinishedHook; + /** xvpHook is called to handle an xvp client message */ + rfbXvpHookPtr xvpHook; + char *sslkeyfile; + char *sslcertfile; + int ipv6port; /**< The port to listen on when using IPv6. */ + char* listen6Interface; + /* We have an additional IPv6 listen socket since there are systems that + don't support dual binding sockets under *any* circumstances, for + instance OpenBSD */ + rfbSocket listen6Sock; + int http6Port; + rfbSocket httpListen6Sock; + /** hook to let client set resolution */ + rfbSetDesktopSizeHookPtr setDesktopSizeHook; + /** Optional hooks to query ExtendedDesktopSize screen information. + * If not set it is assumed only one screen is present spanning entire fb */ + rfbNumberOfExtDesktopScreensPtr numberOfExtDesktopScreensHook; + rfbGetExtDesktopScreenPtr getExtDesktopScreenHook; + /** This value between 0 and 1.0 defines which fraction of the maximum number + of file descriptors LibVNCServer uses before denying new client connections. + It is set to 0.5 per default. */ + float fdQuota; +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + pthread_t listener_thread; + int pipe_notify_listener_thread[2]; +#elif defined(LIBVNCSERVER_HAVE_WIN32THREADS) + uintptr_t listener_thread; +#endif +} rfbScreenInfo, *rfbScreenInfoPtr; + + +/** + * rfbTranslateFnType is the type of translation functions. + */ + +typedef void (*rfbTranslateFnType)(char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height); + + +/* region stuff */ + +struct sraRegion; +typedef struct sraRegion* sraRegionPtr; + +/* + * Per-client structure. + */ + +typedef void (*ClientGoneHookPtr)(struct _rfbClientRec* cl); +typedef void (*ClientFramebufferUpdateRequestHookPtr)(struct _rfbClientRec* cl, rfbFramebufferUpdateRequestMsg* furMsg); + +typedef struct _rfbFileTransferData { + int fd; + int compressionEnabled; + int fileSize; + int numPackets; + int receiving; + int sending; +} rfbFileTransferData; + + +typedef struct _rfbStatList { + uint32_t type; + uint32_t sentCount; + uint32_t bytesSent; + uint32_t bytesSentIfRaw; + uint32_t rcvdCount; + uint32_t bytesRcvd; + uint32_t bytesRcvdIfRaw; + struct _rfbStatList *Next; +} rfbStatList; + +typedef struct _rfbSslCtx rfbSslCtx; +typedef struct _wsCtx wsCtx; + +typedef struct _rfbClientRec { + + /** back pointer to the screen */ + rfbScreenInfoPtr screen; + + /** points to a scaled version of the screen buffer in cl->scaledScreenList */ + rfbScreenInfoPtr scaledScreen; + /** how did the client tell us it wanted the screen changed? Ultra style or palm style? */ + rfbBool PalmVNC; + + + /** private data. You should put any application client specific data + * into a struct and let clientData point to it. Don't forget to + * free the struct via clientGoneHook! + * + * This is useful if the IO functions have to behave client specific. + */ + void* clientData; + ClientGoneHookPtr clientGoneHook; + + rfbSocket sock; + char *host; + + /* RFB protocol minor version number */ + int protocolMajorVersion; + int protocolMinorVersion; + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + pthread_t client_thread; +#elif defined(LIBVNCSERVER_HAVE_WIN32THREADS) + uintptr_t client_thread; +#endif + + /* Note that the RFB_INITIALISATION_SHARED state is provided to support + clients that under some circumstances do not send a ClientInit message. + In particular the Mac OS X built-in VNC client (with protocolMinorVersion + == 889) is one of those. However, it only requires this support under + special circumstances that can only be determined during the initial + authentication. If the right conditions are met this state will be + set (see the auth.c file) when rfbProcessClientInitMessage is called. + + If the state is RFB_INITIALISATION_SHARED we should not expect to receive + any ClientInit message, but instead should proceed to the next stage + of initialisation as though an implicit ClientInit message was received + with a shared-flag of true. (There is currently no corresponding + RFB_INITIALISATION_NOTSHARED state to represent an implicit ClientInit + message with a shared-flag of false because no known existing client + requires such support at this time.) + + Note that software using LibVNCServer to provide a VNC server will only + ever have a chance to see the state field set to + RFB_INITIALISATION_SHARED if the software is multi-threaded and manages + to examine the state field during the extremely brief window after the + 'None' authentication type selection has been received from the built-in + OS X VNC client and before the rfbProcessClientInitMessage function is + called -- control cannot return to the caller during this brief window + while the state field is set to RFB_INITIALISATION_SHARED. */ + + /** Possible client states: */ + enum { + RFB_PROTOCOL_VERSION, /**< establishing protocol version */ + RFB_SECURITY_TYPE, /**< negotiating security (RFB v.3.7) */ + RFB_AUTHENTICATION, /**< authenticating */ + RFB_INITIALISATION, /**< sending initialisation messages */ + RFB_NORMAL, /**< normal protocol messages */ + + /* Ephemeral internal-use states that will never be seen by software + * using LibVNCServer to provide services: */ + + RFB_INITIALISATION_SHARED /**< sending initialisation messages with implicit shared-flag already true */ + } state; + + rfbBool reverseConnection; + rfbBool onHold; + rfbBool readyForSetColourMapEntries; + rfbBool useCopyRect; + int preferredEncoding; + int correMaxWidth, correMaxHeight; + + rfbBool viewOnly; + + /* The following member is only used during VNC authentication */ + uint8_t authChallenge[CHALLENGESIZE]; + + /* The following members represent the update needed to get the client's + framebuffer from its present state to the current state of our + framebuffer. + + If the client does not accept CopyRect encoding then the update is + simply represented as the region of the screen which has been modified + (modifiedRegion). + + If the client does accept CopyRect encoding, then the update consists of + two parts. First we have a single copy from one region of the screen to + another (the destination of the copy is copyRegion), and second we have + the region of the screen which has been modified in some other way + (modifiedRegion). + + Although the copy is of a single region, this region may have many + rectangles. When sending an update, the copyRegion is always sent + before the modifiedRegion. This is because the modifiedRegion may + overlap parts of the screen which are in the source of the copy. + + In fact during normal processing, the modifiedRegion may even overlap + the destination copyRegion. Just before an update is sent we remove + from the copyRegion anything in the modifiedRegion. */ + + sraRegionPtr copyRegion; /**< the destination region of the copy */ + int copyDX, copyDY; /**< the translation by which the copy happens */ + + sraRegionPtr modifiedRegion; + + /** As part of the FramebufferUpdateRequest, a client can express interest + in a subrectangle of the whole framebuffer. This is stored in the + requestedRegion member. In the normal case this is the whole + framebuffer if the client is ready, empty if it's not. */ + + sraRegionPtr requestedRegion; + + /** The following member represents the state of the "deferred update" timer + - when the framebuffer is modified and the client is ready, in most + cases it is more efficient to defer sending the update by a few + milliseconds so that several changes to the framebuffer can be combined + into a single update. */ + + struct timeval startDeferring; + struct timeval startPtrDeferring; + int lastPtrX; + int lastPtrY; + int lastPtrButtons; + + /** translateFn points to the translation function which is used to copy + and translate a rectangle from the framebuffer to an output buffer. */ + + rfbTranslateFnType translateFn; + char *translateLookupTable; + rfbPixelFormat format; + + /** + * UPDATE_BUF_SIZE must be big enough to send at least one whole line of the + * framebuffer. So for a max screen width of say 2K with 32-bit pixels this + * means 8K minimum. + */ + +#define UPDATE_BUF_SIZE 30000 + + char updateBuf[UPDATE_BUF_SIZE]; + int ublen; + + /* statistics */ + struct _rfbStatList *statEncList; + struct _rfbStatList *statMsgList; + int rawBytesEquivalent; + int bytesSent; + +#ifdef LIBVNCSERVER_HAVE_LIBZ + /* zlib encoding -- necessary compression state info per client */ + + struct z_stream_s compStream; + rfbBool compStreamInited; + uint32_t zlibCompressLevel; +#endif +#if defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG) + /** the quality level is also used by ZYWRLE and TightPng */ + int tightQualityLevel; + +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + /* tight encoding -- preserve zlib streams' state for each client */ + z_stream zsStruct[4]; + rfbBool zsActive[4]; + int zsLevel[4]; + int tightCompressLevel; +#endif +#endif + + /* Ultra Encoding support */ + rfbBool compStreamInitedLZO; + char *lzoWrkMem; + + rfbFileTransferData fileTransfer; + + int lastKeyboardLedState; /**< keep track of last value so we can send *change* events */ + rfbBool enableSupportedMessages; /**< client supports SupportedMessages encoding */ + rfbBool enableSupportedEncodings; /**< client supports SupportedEncodings encoding */ + rfbBool enableServerIdentity; /**< client supports ServerIdentity encoding */ + rfbBool enableKeyboardLedState; /**< client supports KeyboardState encoding */ + rfbBool enableLastRectEncoding; /**< client supports LastRect encoding */ + rfbBool enableCursorShapeUpdates; /**< client supports cursor shape updates */ + rfbBool enableCursorPosUpdates; /**< client supports cursor position updates */ + rfbBool useRichCursorEncoding; /**< rfbEncodingRichCursor is preferred */ + rfbBool cursorWasChanged; /**< cursor shape update should be sent */ + rfbBool cursorWasMoved; /**< cursor position update should be sent */ + int cursorX,cursorY; /**< the coordinates of the cursor, + if enableCursorShapeUpdates = FALSE */ + + rfbBool useNewFBSize; /**< client supports NewFBSize encoding */ + rfbBool newFBSizePending; /**< framebuffer size was changed */ + + struct _rfbClientRec *prev; + struct _rfbClientRec *next; + +#if defined(LIBVNCSERVER_HAVE_LIBPTHREAD) || defined(LIBVNCSERVER_HAVE_WIN32THREADS) + /** whenever a client is referenced, the refCount has to be incremented + and afterwards decremented, so that the client is not cleaned up + while being referenced. + Use the functions rfbIncrClientRef(cl) and rfbDecrClientRef(cl); + */ + int refCount; + MUTEX(refCountMutex); + COND(deleteCond); + + MUTEX(outputMutex); + MUTEX(updateMutex); + COND(updateCond); +#endif + +#ifdef LIBVNCSERVER_HAVE_LIBZ + void* zrleData; + int zywrleLevel; + int zywrleBuf[rfbZRLETileWidth * rfbZRLETileHeight]; +#endif + + /** if progressive updating is on, this variable holds the current + * y coordinate of the progressive slice. */ + int progressiveSliceY; + + rfbExtensionData* extensions; + + /** for threaded zrle */ + char *zrleBeforeBuf; + void *paletteHelper; + + /** for thread safety for rfbSendFBUpdate() */ +#if defined(LIBVNCSERVER_HAVE_LIBPTHREAD) || defined(LIBVNCSERVER_HAVE_WIN32THREADS) +#define LIBVNCSERVER_SEND_MUTEX + MUTEX(sendMutex); +#endif + + /* buffers to hold pixel data before and after encoding. + per-client for thread safety */ + char *beforeEncBuf; + int beforeEncBufSize; + char *afterEncBuf; + int afterEncBufSize; + int afterEncBufLen; +#if defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG) + uint32_t tightEncoding; /* rfbEncodingTight or rfbEncodingTightPng */ +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + /* TurboVNC Encoding support (extends TightVNC) */ + int turboSubsampLevel; + int turboQualityLevel; /* 1-100 scale */ +#endif +#endif + rfbSslCtx *sslctx; + wsCtx *wsctx; + char *wspath; /* Requests path component */ +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + int pipe_notify_client_thread[2]; +#endif + + /** + * clientFramebufferUpdateRequestHook is called when a client requests a frame + * buffer update. + */ + ClientFramebufferUpdateRequestHookPtr clientFramebufferUpdateRequestHook; + + rfbBool useExtDesktopSize; + int requestedDesktopSizeChange; + int lastDesktopSizeChangeError; + +#ifdef LIBVNCSERVER_HAVE_LIBZ + rfbBool enableExtendedClipboard; + uint32_t extClipboardUserCap; + uint32_t extClipboardMaxUnsolicitedSize; + char *extClipboardData; + int extClipboardDataSize; +#endif +} rfbClientRec, *rfbClientPtr; + +/** + * This macro is used to test whether there is a framebuffer update needing to + * be sent to the client. + */ + +#define FB_UPDATE_PENDING(cl) \ + (((cl)->enableCursorShapeUpdates && (cl)->cursorWasChanged) || \ + (((cl)->enableCursorShapeUpdates == FALSE && \ + ((cl)->cursorX != (cl)->screen->cursorX || \ + (cl)->cursorY != (cl)->screen->cursorY))) || \ + ((cl)->useNewFBSize && (cl)->newFBSizePending) || \ + ((cl)->enableCursorPosUpdates && (cl)->cursorWasMoved) || \ + !sraRgnEmpty((cl)->copyRegion) || !sraRgnEmpty((cl)->modifiedRegion)) + +/* + * Macros for endian swapping. + */ + +#define Swap16(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) + +#define Swap24(l) ((((l) & 0xff) << 16) | (((l) >> 16) & 0xff) | \ + (((l) & 0x00ff00))) + +#define Swap32(l) ((((l) >> 24) & 0x000000ff)| \ + (((l) & 0x00ff0000) >> 8) | \ + (((l) & 0x0000ff00) << 8) | \ + (((l) & 0x000000ff) << 24)) + + +extern char rfbEndianTest; + +#define Swap16IfLE(s) (rfbEndianTest ? Swap16(s) : (s)) +#define Swap24IfLE(l) (rfbEndianTest ? Swap24(l) : (l)) +#define Swap32IfLE(l) (rfbEndianTest ? Swap32(l) : (l)) + +/* UltraVNC uses some windows structures unmodified, so the viewer expects LittleEndian Data */ +#define Swap16IfBE(s) (rfbEndianTest ? (s) : Swap16(s)) +#define Swap24IfBE(l) (rfbEndianTest ? (l) : Swap24(l)) +#define Swap32IfBE(l) (rfbEndianTest ? (l) : Swap32(l)) + +/* sockets.c */ + +extern int rfbMaxClientWait; + +extern void rfbInitSockets(rfbScreenInfoPtr rfbScreen); +extern void rfbShutdownSockets(rfbScreenInfoPtr rfbScreen); +extern void rfbDisconnectUDPSock(rfbScreenInfoPtr rfbScreen); +extern void rfbCloseClient(rfbClientPtr cl); +extern int rfbReadExact(rfbClientPtr cl, char *buf, int len); +extern int rfbReadExactTimeout(rfbClientPtr cl, char *buf, int len,int timeout); +extern int rfbPeekExactTimeout(rfbClientPtr cl, char *buf, int len,int timeout); +extern int rfbWriteExact(rfbClientPtr cl, const char *buf, int len); +extern int rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec); +extern rfbSocket rfbConnect(rfbScreenInfoPtr rfbScreen, char* host, int port); +extern rfbSocket rfbConnectToTcpAddr(char* host, int port); +extern rfbSocket rfbListenOnTCPPort(int port, in_addr_t iface); +extern rfbSocket rfbListenOnTCP6Port(int port, const char* iface); +extern rfbSocket rfbListenOnUDPPort(int port, in_addr_t iface); +extern int rfbStringToAddr(char* string,in_addr_t* addr); +extern rfbBool rfbSetNonBlocking(rfbSocket sock); + +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS +/* websockets.c */ + +extern rfbBool webSocketsCheck(rfbClientPtr cl); +extern rfbBool webSocketCheckDisconnect(rfbClientPtr cl); +extern int webSocketsEncode(rfbClientPtr cl, const char *src, int len, char **dst); +extern int webSocketsDecode(rfbClientPtr cl, char *dst, int len); +extern rfbBool webSocketsHasDataInBuffer(rfbClientPtr cl); +#endif + +/* rfbserver.c */ + +/* Routines to iterate over the client list in a thread-safe way. + Only a single iterator can be in use at a time process-wide. */ +typedef struct rfbClientIterator *rfbClientIteratorPtr; + +extern void rfbClientListInit(rfbScreenInfoPtr rfbScreen); +extern rfbClientIteratorPtr rfbGetClientIterator(rfbScreenInfoPtr rfbScreen); +extern rfbClientPtr rfbClientIteratorNext(rfbClientIteratorPtr iterator); +extern void rfbReleaseClientIterator(rfbClientIteratorPtr iterator); +extern void rfbIncrClientRef(rfbClientPtr cl); +extern void rfbDecrClientRef(rfbClientPtr cl); + +extern void rfbNewClientConnection(rfbScreenInfoPtr rfbScreen,rfbSocket sock); +extern rfbClientPtr rfbNewClient(rfbScreenInfoPtr rfbScreen,rfbSocket sock); +extern rfbClientPtr rfbNewUDPClient(rfbScreenInfoPtr rfbScreen); +extern rfbClientPtr rfbReverseConnection(rfbScreenInfoPtr rfbScreen,char *host, int port); +extern void rfbClientConnectionGone(rfbClientPtr cl); +extern void rfbProcessClientMessage(rfbClientPtr cl); +extern void rfbClientConnFailed(rfbClientPtr cl, const char *reason); +extern void rfbNewUDPConnection(rfbScreenInfoPtr rfbScreen,rfbSocket sock); +extern void rfbProcessUDPInput(rfbScreenInfoPtr rfbScreen); +extern rfbBool rfbSendFramebufferUpdate(rfbClientPtr cl, sraRegionPtr updateRegion); +extern rfbBool rfbSendRectEncodingRaw(rfbClientPtr cl, int x,int y,int w,int h); +extern rfbBool rfbSendUpdateBuf(rfbClientPtr cl); +extern void rfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len); +#ifdef LIBVNCSERVER_HAVE_LIBZ +extern void rfbSendServerCutTextUTF8(rfbScreenInfoPtr rfbScreen,char *str, int len, char *fallbackLatin1Str, int latin1Len); +#endif +extern rfbBool rfbSendCopyRegion(rfbClientPtr cl,sraRegionPtr reg,int dx,int dy); +extern rfbBool rfbSendLastRectMarker(rfbClientPtr cl); +extern rfbBool rfbSendNewFBSize(rfbClientPtr cl, int w, int h); +extern rfbBool rfbSendExtDesktopSize(rfbClientPtr cl, int w, int h); +extern rfbBool rfbSendSetColourMapEntries(rfbClientPtr cl, int firstColour, int nColours); +extern void rfbSendBell(rfbScreenInfoPtr rfbScreen); + +extern char *rfbProcessFileTransferReadBuffer(rfbClientPtr cl, uint32_t length); +extern rfbBool rfbSendFileTransferChunk(rfbClientPtr cl); +extern rfbBool rfbSendDirContent(rfbClientPtr cl, int length, char *buffer); +extern rfbBool rfbSendFileTransferMessage(rfbClientPtr cl, uint8_t contentType, uint8_t contentParam, uint32_t size, uint32_t length, const char *buffer); +extern char *rfbProcessFileTransferReadBuffer(rfbClientPtr cl, uint32_t length); +extern rfbBool rfbProcessFileTransfer(rfbClientPtr cl, uint8_t contentType, uint8_t contentParam, uint32_t size, uint32_t length); + +void rfbGotXCutText(rfbScreenInfoPtr rfbScreen, char *str, int len); + +/* translate.c */ + +extern rfbBool rfbEconomicTranslate; + +extern void rfbTranslateNone(char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height); +extern rfbBool rfbSetTranslateFunction(rfbClientPtr cl); +extern rfbBool rfbSetClientColourMap(rfbClientPtr cl, int firstColour, int nColours); +extern void rfbSetClientColourMaps(rfbScreenInfoPtr rfbScreen, int firstColour, int nColours); + +/* httpd.c */ + +extern void rfbHttpInitSockets(rfbScreenInfoPtr rfbScreen); +extern void rfbHttpShutdownSockets(rfbScreenInfoPtr rfbScreen); +extern void rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen); + + + +/* auth.c */ + +extern void rfbAuthNewClient(rfbClientPtr cl); +extern void rfbProcessClientSecurityType(rfbClientPtr cl); +extern void rfbAuthProcessClientMessage(rfbClientPtr cl); +extern void rfbRegisterSecurityHandler(rfbSecurityHandler* handler); +extern void rfbUnregisterSecurityHandler(rfbSecurityHandler* handler); + +/* rre.c */ + +extern rfbBool rfbSendRectEncodingRRE(rfbClientPtr cl, int x,int y,int w,int h); + + +/* corre.c */ + +extern rfbBool rfbSendRectEncodingCoRRE(rfbClientPtr cl, int x,int y,int w,int h); + + +/* hextile.c */ + +extern rfbBool rfbSendRectEncodingHextile(rfbClientPtr cl, int x, int y, int w, + int h); + +/* ultra.c */ + +/* Set maximum ultra rectangle size in pixels. Always allow at least + * two scan lines. + */ +#define ULTRA_MAX_RECT_SIZE (128*256) +#define ULTRA_MAX_SIZE(min) ((( min * 2 ) > ULTRA_MAX_RECT_SIZE ) ? \ + ( min * 2 ) : ULTRA_MAX_RECT_SIZE ) + +extern rfbBool rfbSendRectEncodingUltra(rfbClientPtr cl, int x,int y,int w,int h); + + +#ifdef LIBVNCSERVER_HAVE_LIBZ +/* zlib.c */ + +/** Minimum zlib rectangle size in bytes. Anything smaller will + * not compress well due to overhead. + */ +#define VNC_ENCODE_ZLIB_MIN_COMP_SIZE (17) + +/* Set maximum zlib rectangle size in pixels. Always allow at least + * two scan lines. + */ +#define ZLIB_MAX_RECT_SIZE (128*256) +#define ZLIB_MAX_SIZE(min) ((( min * 2 ) > ZLIB_MAX_RECT_SIZE ) ? \ + ( min * 2 ) : ZLIB_MAX_RECT_SIZE ) + +extern rfbBool rfbSendRectEncodingZlib(rfbClientPtr cl, int x, int y, int w, + int h); + +#ifdef LIBVNCSERVER_HAVE_LIBJPEG +/* tight.c */ + +#define TIGHT_DEFAULT_COMPRESSION 6 +#define TURBO_DEFAULT_SUBSAMP 0 + +extern rfbBool rfbTightDisableGradient; + +extern int rfbNumCodedRectsTight(rfbClientPtr cl, int x,int y,int w,int h); + +extern rfbBool rfbSendRectEncodingTight(rfbClientPtr cl, int x,int y,int w,int h); +extern rfbBool rfbSendTightHeader(rfbClientPtr cl, int x, int y, int w, int h); +extern rfbBool rfbSendCompressedDataTight(rfbClientPtr cl, char *buf, int compressedLen); + +#if defined(LIBVNCSERVER_HAVE_LIBPNG) +extern rfbBool rfbSendRectEncodingTightPng(rfbClientPtr cl, int x,int y,int w,int h); +#endif + +#endif +#endif + + +/* cursor.c */ + +typedef struct rfbCursor { + /** set this to true if LibVNCServer has to free this cursor */ + rfbBool cleanup, cleanupSource, cleanupMask, cleanupRichSource; + unsigned char *source; /**< points to bits */ + unsigned char *mask; /**< points to bits */ + unsigned short width, height, xhot, yhot; /**< metrics */ + unsigned short foreRed, foreGreen, foreBlue; /**< device-independent colour */ + unsigned short backRed, backGreen, backBlue; /**< device-independent colour */ + unsigned char *richSource; /**< source bytes for a rich cursor */ + unsigned char *alphaSource; /**< source for alpha blending info */ + rfbBool alphaPreMultiplied; /**< if richSource already has alpha applied */ +} rfbCursor, *rfbCursorPtr; +extern unsigned char rfbReverseByte[0x100]; + +extern rfbBool rfbSendCursorShape(rfbClientPtr cl/*, rfbScreenInfoPtr pScreen*/); +extern rfbBool rfbSendCursorPos(rfbClientPtr cl); +extern void rfbConvertLSBCursorBitmapOrMask(int width,int height,unsigned char* bitmap); +extern rfbCursorPtr rfbMakeXCursor(int width,int height,char* cursorString,char* maskString); +extern char* rfbMakeMaskForXCursor(int width,int height,char* cursorString); +extern char* rfbMakeMaskFromAlphaSource(int width,int height,unsigned char* alphaSource); +extern void rfbMakeXCursorFromRichCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor); +extern void rfbMakeRichCursorFromXCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor); +extern void rfbFreeCursor(rfbCursorPtr cursor); +extern void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c); + +/** cursor handling for the pointer */ +extern void rfbDefaultPtrAddEvent(int buttonMask,int x,int y,rfbClientPtr cl); + +/* zrle.c */ +#ifdef LIBVNCSERVER_HAVE_LIBZ +extern rfbBool rfbSendRectEncodingZRLE(rfbClientPtr cl, int x, int y, int w,int h); +#endif + +/* stats.c */ + +extern void rfbResetStats(rfbClientPtr cl); +extern void rfbPrintStats(rfbClientPtr cl); + +/* font.c */ + +typedef struct rfbFontData { + unsigned char* data; + /** + metaData is a 256*5 array: + for each character + (offset,width,height,x,y) + */ + int* metaData; +} rfbFontData,* rfbFontDataPtr; + +int rfbDrawChar(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,unsigned char c,rfbPixel colour); +void rfbDrawString(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,const char* string,rfbPixel colour); +/** if colour==backColour, background is transparent */ +int rfbDrawCharWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,unsigned char c,int x1,int y1,int x2,int y2,rfbPixel colour,rfbPixel backColour); +void rfbDrawStringWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,const char* string,int x1,int y1,int x2,int y2,rfbPixel colour,rfbPixel backColour); +int rfbWidthOfString(rfbFontDataPtr font,const char* string); +int rfbWidthOfChar(rfbFontDataPtr font,unsigned char c); +void rfbFontBBox(rfbFontDataPtr font,unsigned char c,int* x1,int* y1,int* x2,int* y2); +/** this returns the smallest box enclosing any character of font. */ +void rfbWholeFontBBox(rfbFontDataPtr font,int *x1, int *y1, int *x2, int *y2); + +/** dynamically load a linux console font (4096 bytes, 256 glyphs a 8x16 */ +rfbFontDataPtr rfbLoadConsoleFont(char *filename); +/** free a dynamically loaded font */ +void rfbFreeFont(rfbFontDataPtr font); + +/* draw.c */ + +void rfbFillRect(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,rfbPixel col); +void rfbDrawPixel(rfbScreenInfoPtr s,int x,int y,rfbPixel col); +void rfbDrawLine(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,rfbPixel col); + +/* selbox.c */ + +/** this opens a modal select box. list is an array of strings, the end marked + with a NULL. + It returns the index in the list or -1 if cancelled or something else + wasn't kosher. */ +typedef void (*SelectionChangedHookPtr)(int _index); +extern int rfbSelectBox(rfbScreenInfoPtr rfbScreen, + rfbFontDataPtr font, char** list, + int x1, int y1, int x2, int y2, + rfbPixel foreColour, rfbPixel backColour, + int border,SelectionChangedHookPtr selChangedHook); + +/* cargs.c */ + +extern void rfbUsage(void); +extern void rfbPurgeArguments(int* argc,int* position,int count,char *argv[]); +extern rfbBool rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[]); +extern rfbBool rfbProcessSizeArguments(int* width,int* height,int* bpp,int* argc, char *argv[]); + +/* main.c */ + +extern void rfbLogEnable(int enabled); +typedef void (*rfbLogProc)(const char *format, ...); +extern rfbLogProc rfbLog, rfbErr; +extern void rfbLogPerror(const char *str); + +void rfbScheduleCopyRect(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2,int dx,int dy); +void rfbScheduleCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy); + +void rfbDoCopyRect(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2,int dx,int dy); +void rfbDoCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy); + +void rfbMarkRectAsModified(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2); +void rfbMarkRegionAsModified(rfbScreenInfoPtr rfbScreen,sraRegionPtr modRegion); +void rfbDoNothingWithClient(rfbClientPtr cl); +enum rfbNewClientAction defaultNewClientHook(rfbClientPtr cl); +void rfbRegisterProtocolExtension(rfbProtocolExtension* extension); +void rfbUnregisterProtocolExtension(rfbProtocolExtension* extension); +struct _rfbProtocolExtension* rfbGetExtensionIterator(void); +void rfbReleaseExtensionIterator(void); +rfbBool rfbEnableExtension(rfbClientPtr cl, rfbProtocolExtension* extension, + void* data); +rfbBool rfbDisableExtension(rfbClientPtr cl, rfbProtocolExtension* extension); +void* rfbGetExtensionClientData(rfbClientPtr cl, rfbProtocolExtension* extension); + +/** to check against plain passwords */ +rfbBool rfbCheckPasswordByList(rfbClientPtr cl,const char* response,int len); + +/* functions to make a vnc server */ +extern rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv, + int width,int height,int bitsPerSample,int samplesPerPixel, + int bytesPerPixel); +extern void rfbInitServer(rfbScreenInfoPtr rfbScreen); +extern void rfbShutdownServer(rfbScreenInfoPtr rfbScreen,rfbBool disconnectClients); +extern void rfbNewFramebuffer(rfbScreenInfoPtr rfbScreen,char *framebuffer, + int width,int height, int bitsPerSample,int samplesPerPixel, + int bytesPerPixel); + +extern void rfbScreenCleanup(rfbScreenInfoPtr screenInfo); +extern void rfbSetServerVersionIdentity(rfbScreenInfoPtr screen, char *fmt, ...); + +/* functions to accept/refuse a client that has been put on hold + by a NewClientHookPtr function. Must not be called in other + situations. */ +extern void rfbStartOnHoldClient(rfbClientPtr cl); +extern void rfbRefuseOnHoldClient(rfbClientPtr cl); + +/* call one of these two functions to service the vnc clients. + usec are the microseconds the select on the fds waits. + if you are using the event loop, set this to some value > 0, so the + server doesn't get a high load just by listening. + rfbProcessEvents() returns TRUE if an update was pending. */ + +extern void rfbRunEventLoop(rfbScreenInfoPtr screenInfo, long usec, rfbBool runInBackground); +extern rfbBool rfbProcessEvents(rfbScreenInfoPtr screenInfo,long usec); +extern rfbBool rfbIsActive(rfbScreenInfoPtr screenInfo); + +/** + * Register the TightVNC-1.3.x file transfer extension. + * NB That TightVNC-2.x uses a different, incompatible file transfer protocol. + */ +void rfbRegisterTightVNCFileTransferExtension(void); +/** + * Unregister the TightVNC-1.3.x file transfer extension. + * NB That TightVNC-2.x uses a different, incompatible file transfer protocol. + */ +void rfbUnregisterTightVNCFileTransferExtension(void); + +/* Statistics */ +extern char *messageNameServer2Client(uint32_t type, char *buf, int len); +extern char *messageNameClient2Server(uint32_t type, char *buf, int len); +extern char *encodingName(uint32_t enc, char *buf, int len); + +extern rfbStatList *rfbStatLookupEncoding(rfbClientPtr cl, uint32_t type); +extern rfbStatList *rfbStatLookupMessage(rfbClientPtr cl, uint32_t type); + +/* Each call to rfbStatRecord* adds one to the rect count for that type */ +extern void rfbStatRecordEncodingSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +extern void rfbStatRecordEncodingSentAdd(rfbClientPtr cl, uint32_t type, int byteCount); /* Specifically for tight encoding */ +extern void rfbStatRecordEncodingRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +extern void rfbStatRecordMessageSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +extern void rfbStatRecordMessageRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +extern void rfbResetStats(rfbClientPtr cl); +extern void rfbPrintStats(rfbClientPtr cl); + +extern int rfbStatGetSentBytes(rfbClientPtr cl); +extern int rfbStatGetSentBytesIfRaw(rfbClientPtr cl); +extern int rfbStatGetRcvdBytes(rfbClientPtr cl); +extern int rfbStatGetRcvdBytesIfRaw(rfbClientPtr cl); +extern int rfbStatGetMessageCountSent(rfbClientPtr cl, uint32_t type); +extern int rfbStatGetMessageCountRcvd(rfbClientPtr cl, uint32_t type); +extern int rfbStatGetEncodingCountSent(rfbClientPtr cl, uint32_t type); +extern int rfbStatGetEncodingCountRcvd(rfbClientPtr cl, uint32_t type); + +/** Set which version you want to advertise 3.3, 3.6, 3.7 and 3.8 are currently supported*/ +extern void rfbSetProtocolVersion(rfbScreenInfoPtr rfbScreen, int major_, int minor_); + +/** send a TextChat message to a client */ +extern rfbBool rfbSendTextChatMessage(rfbClientPtr cl, uint32_t length, char *buffer); + + +/* + * Additions for Qt event loop integration + * Original idea taken from vino. + */ +rfbBool rfbProcessNewConnection(rfbScreenInfoPtr rfbScreen); +rfbBool rfbUpdateClient(rfbClientPtr cl); + + +#if(defined __cplusplus) +} +#endif + +/** + * @} + */ + + +/** + @page libvncserver_doc LibVNCServer Documentation + @section create_server Creating a server instance + To make a server, you just have to initialise a server structure using the + function rfbGetScreen(), like + @code + rfbScreenInfoPtr screen = + rfbGetScreen(argc,argv,screenwidth,screenheight,8,3,bpp); + @endcode + where byte per pixel should be 1, 2 or 4. If performance doesn't matter, + you may try bpp=3 (internally one cannot use native data types in this + case; if you want to use this, look at pnmshow24.c). + + You then can set hooks and io functions (see @ref making_it_interactive) or other + options (see @ref server_options). + + And you allocate the frame buffer like this: + @code + screen->frameBuffer = (char*)malloc(screenwidth*screenheight*bpp); + @endcode + After that, you initialize the server, like + @code + rfbInitServer(screen); + @endcode + You can use a blocking event loop, a background (pthread based) event loop, + or implement your own using the rfbProcessEvents() function. + + @subsection server_options Optional Server Features + + These options have to be set between rfbGetScreen() and rfbInitServer(). + + If you already have a socket to talk to, just set rfbScreenInfo::inetdSock + (originally this is for inetd handling, but why not use it for your purpose?). + + To also start an HTTP server (running on port 5800+display_number), you have + to set rfbScreenInfo::httpDir to a directory containing vncviewer.jar and + index.vnc (like the included "webclients" directory). + + @section making_it_interactive Making it interactive + + Whenever you draw something, you have to call + @code + rfbMarkRectAsModified(screen,x1,y1,x2,y2). + @endcode + This tells LibVNCServer to send updates to all connected clients. + + There exist the following IO functions as members of rfbScreen: + rfbScreenInfo::kbdAddEvent(), rfbScreenInfo::kbdReleaseAllKeys(), rfbScreenInfo::ptrAddEvent(), + rfbScreenInfo::setXCutText() and rfbScreenInfo::setXCutTextUTF8() + + rfbScreenInfo::kbdAddEvent() + is called when a key is pressed. + rfbScreenInfo::kbdReleaseAllKeys() + is not called at all (maybe in the future). + rfbScreenInfo::ptrAddEvent() + is called when the mouse moves or a button is pressed. + WARNING: if you want to have proper cursor handling, call + rfbDefaultPtrAddEvent() + in your own function. This sets the coordinates of the cursor. + rfbScreenInfo::setXCutText() + is called when the selection changes. + rfbScreenInfo::setXCutTextUTF8() + is called when the selection changes and the ExtendedClipboard extension is enabled. + + There are only two hooks: + rfbScreenInfo::newClientHook() + is called when a new client has connected. + rfbScreenInfo::displayHook() + is called just before a frame buffer update is sent. + + You can also override the following methods: + rfbScreenInfo::getCursorPtr() + This could be used to make an animated cursor (if you really want ...) + rfbScreenInfo::setTranslateFunction() + If you insist on colour maps or something more obscure, you have to + implement this. Default is a trueColour mapping. + + @section cursor_handling Cursor handling + + The screen holds a pointer + rfbScreenInfo::cursor + to the current cursor. Whenever you set it, remember that any dynamically + created cursor (like return value from rfbMakeXCursor()) is not free'd! + + The rfbCursor structure consists mainly of a mask and a source. The rfbCursor::mask + describes, which pixels are drawn for the cursor (a cursor needn't be + rectangular). The rfbCursor::source describes, which colour those pixels should have. + + The standard is an XCursor: a cursor with a foreground and a background + colour (stored in backRed,backGreen,backBlue and the same for foreground + in a range from 0-0xffff). Therefore, the arrays "mask" and "source" + contain pixels as single bits stored in bytes in MSB order. The rows are + padded, such that each row begins with a new byte (i.e. a 10x4 + cursor's mask has 2x4 bytes, because 2 bytes are needed to hold 10 bits). + + It is however very easy to make a cursor like this: + @code + char* cur=" " + " xx " + " x " + " "; + char* mask="xxxx" + "xxxx" + "xxxx" + "xxx "; + rfbCursorPtr c=rfbMakeXCursor(4,4,cur,mask); + @endcode + You can even set rfbCursor::mask to NULL in this call and LibVNCServer will calculate + a mask for you (dynamically, so you have to free it yourself). + + There is also an array named rfbCursor::richSource for colourful cursors. They have + the same format as the frameBuffer (i.e. if the server is 32 bit, + a 10x4 cursor has 4x10x4 bytes). + + @section screen_client_difference What is the difference between rfbScreenInfoPtr and rfbClientPtr? + + The rfbScreenInfoPtr is a pointer to a rfbScreenInfo structure, which + holds information about the server, like pixel format, io functions, + frame buffer etc. The rfbClientPtr is a pointer to an rfbClientRec structure, which holds + information about a client, like pixel format, socket of the + connection, etc. A server can have several clients, but needn't have any. So, if you + have a server and three clients are connected, you have one instance + of a rfbScreenInfo and three instances of rfbClientRec's. + + The rfbClientRec structure holds a member rfbClientRec::screen which points to the server. + So, to access the server from the client structure, you use client->screen. + + To access all clients from a server be sure to use the provided iterator + rfbGetClientIterator() + with + rfbClientIteratorNext() + and + rfbReleaseClientIterator() + to prevent thread clashes. + + @section example_code Example Code + + There are two documented examples included: + - example.c, a shared scribble sheet + - pnmshow.c, a program to show PNMs (pictures) over the net. + + The examples are not too well documented, but easy straight forward and a + good starting point. + + Try example.c: it outputs on which port it listens (default: 5900), so it is + display 0. To view, call @code vncviewer :0 @endcode + You should see a sheet with a gradient and "Hello World!" written on it. Try + to paint something. Note that every time you click, there is some bigger blot, + whereas when you drag the mouse while clicked you draw a line. The size of the + blot depends on the mouse button you click. Open a second vncviewer with + the same parameters and watch it as you paint in the other window. This also + works over internet. You just have to know either the name or the IP of your + machine. Then it is @code vncviewer machine.where.example.runs.com:0 @endcode + or similar for the remote client. Now you are ready to type something. Be sure + that your mouse sits still, because every time the mouse moves, the cursor is + reset to the position of the pointer! If you are done with that demo, press + the down or up arrows. If your viewer supports it, then the dimensions of the + sheet change. Just press Escape in the viewer. Note that the server still + runs, even if you closed both windows. When you reconnect now, everything you + painted and wrote is still there. You can press "Page Up" for a blank page. + + The demo pnmshow.c is much simpler: you either provide a filename as argument + or pipe a file through stdin. Note that the file has to be a raw pnm/ppm file, + i.e. a truecolour graphics. Only the Escape key is implemented. This may be + the best starting point if you want to learn how to use LibVNCServer. You + are confronted with the fact that the bytes per pixel can only be 8, 16 or 32. +*/ + +#endif diff --git a/rfb/rfbclient.h b/rfb/rfbclient.h new file mode 100644 index 0000000..9d33dc0 --- /dev/null +++ b/rfb/rfbclient.h @@ -0,0 +1,833 @@ +#ifndef RFBCLIENT_H +#define RFBCLIENT_H + +/** + * @defgroup libvncclient_api LibVNCClient API Reference + * @{ + */ + +/* + * Copyright (C) 2017 D. R. Commander. All Rights Reserved. + * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. + * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/** + * @file rfbclient.h + */ + +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN /* Prevent loading any Winsock 1.x headers from windows.h */ +#ifdef _MSC_VER +#pragma warning(disable:4996) +#endif +#endif + +#if defined(ANDROID) || defined(LIBVNCSERVER_HAVE_ANDROID) +#include +#include +#endif + +#include +#include +#include +#if LIBVNCSERVER_HAVE_SYS_TIME_H +#include +#endif +#if LIBVNCSERVER_HAVE_UNISTD_H +#include +#endif +#include +#include +#include + +#ifdef LIBVNCSERVER_HAVE_SASL +#include +#endif /* LIBVNCSERVER_HAVE_SASL */ + +#define rfbClientSwap16IfLE(s) \ + (*(char *)&client->endianTest ? ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) : (s)) + +#define rfbClientSwap32IfLE(l) \ + (*(char *)&client->endianTest ? ((((l) >> 24) & 0x000000ff) | \ + (((l) & 0x00ff0000) >> 8) | \ + (((l) & 0x0000ff00) << 8) | \ + (((l) & 0x000000ff) << 24)) : (l)) + +#define rfbClientSwap64IfLE(l) \ + (*(char *)&client->endianTest ? ((((l) >> 56 ) & 0x00000000000000ffULL) | \ + (((l) & 0x00ff000000000000ULL) >> 40) | \ + (((l) & 0x0000ff0000000000ULL) >> 24) | \ + (((l) & 0x000000ff00000000ULL) >> 8) | \ + (((l) & 0x00000000ff000000ULL) << 8) | \ + (((l) & 0x0000000000ff0000ULL) << 24) | \ + (((l) & 0x000000000000ff00ULL) << 40) | \ + (((l) & 0x00000000000000ffULL) << 56)) : (l)) + +#define FLASH_PORT_OFFSET 5400 +#define LISTEN_PORT_OFFSET 5500 +#define TUNNEL_PORT_OFFSET 5500 +#define SERVER_PORT_OFFSET 5900 + +#define DEFAULT_CONNECT_TIMEOUT 60 +#define DEFAULT_READ_TIMEOUT 0 + +#define DEFAULT_SSH_CMD "/usr/bin/ssh" +#define DEFAULT_TUNNEL_CMD \ + (DEFAULT_SSH_CMD " -f -L %L:localhost:%R %H sleep 20") +#define DEFAULT_VIA_CMD \ + (DEFAULT_SSH_CMD " -f -L %L:%H:%R %G sleep 20") + +#if(defined __cplusplus) +extern "C" +{ +#endif + +/** vncrec */ + +typedef struct { + FILE* file; + struct timeval tv; + rfbBool readTimestamp; + rfbBool doNotSleep; +} rfbVNCRec; + +/** client data */ + +typedef struct rfbClientData { + void* tag; + void* data; + struct rfbClientData* next; +} rfbClientData; + +/** app data (belongs into rfbClient?) */ + +typedef struct { + rfbBool shareDesktop; + rfbBool viewOnly; + + const char* encodingsString; + + rfbBool useBGR233; + int nColours; + rfbBool forceOwnCmap; + rfbBool forceTrueColour; + int requestedDepth; + + int compressLevel; + int qualityLevel; + rfbBool enableJPEG; + rfbBool useRemoteCursor; + rfbBool palmVNC; /**< use palmvnc specific SetScale (vs ultravnc) */ + int scaleSetting; /**< 0 means no scale set, else 1/scaleSetting */ +} AppData; + +/** For GetCredentialProc callback function to return */ +typedef union _rfbCredential +{ + /** X509 (VeNCrypt) */ + struct + { + char *x509CACertFile; + char *x509CACrlFile; + char *x509ClientCertFile; + char *x509ClientKeyFile; + uint8_t x509CrlVerifyMode; /* Only required for OpenSSL - see meanings below */ + } x509Credential; + /** Plain (VeNCrypt), MSLogon (UltraVNC) */ + struct + { + char *username; + char *password; + } userCredential; +} rfbCredential; + +#define rfbCredentialTypeX509 1 +#define rfbCredentialTypeUser 2 + +/* When using OpenSSL, CRLs can be included in both the x509CACrlFile and appended + to the x509CACertFile as is common with OpenSSL. When rfbX509CrlVerifyAll is + specified the CRL list must include CRLs for all certificates in the chain */ +#define rfbX509CrlVerifyNone 0 /* No CRL checking is performed */ +#define rfbX509CrlVerifyClient 1 /* Only the leaf server certificate is checked */ +#define rfbX509CrlVerifyAll 2 /* All certificates in the server chain are checked */ + +struct _rfbClient; + +/** + * Handles a text chat message. If your application should accept text messages + * from the server, define a function with this prototype and set + * client->HandleTextChat to a pointer to that function subsequent to your + * rfbGetClient() call. + * @param client The client which called the text chat handler + * @param value text length if text != NULL, or one of rfbTextChatOpen, + * rfbTextChatClose, rfbTextChatFinished if text == NULL + * @param text The text message from the server + */ +typedef void (*HandleTextChatProc)(struct _rfbClient* client, int value, char *text); +/** + * Handles XVP server messages. If your application sends XVP messages to the + * server, you'll want to handle the server's XVP_FAIL and XVP_INIT responses. + * Define a function with this prototype and set client->HandleXvpMsg to a + * pointer to that function subsequent to your rfbGetClient() call. + * @param client The client which called the XVP message handler + * @param version The highest XVP extension version that the server supports + * @param opcode The opcode. 0 is XVP_FAIL, 1 is XVP_INIT + */ +typedef void (*HandleXvpMsgProc)(struct _rfbClient* client, uint8_t version, uint8_t opcode); +typedef void (*HandleKeyboardLedStateProc)(struct _rfbClient* client, int value, int pad); +typedef rfbBool (*HandleCursorPosProc)(struct _rfbClient* client, int x, int y); +typedef void (*SoftCursorLockAreaProc)(struct _rfbClient* client, int x, int y, int w, int h); +typedef void (*SoftCursorUnlockScreenProc)(struct _rfbClient* client); +/** + Callback indicating that a rectangular area of the client's framebuffer was updated. + As a server will usually send several rects per rfbFramebufferUpdate message, this + callback is usually called multiple times per rfbFramebufferUpdate message. + @param client The client whose framebuffer was (partially) updated + @param x The x-coordinate of the upper left corner of the updated rectangle + @param y The y-coordinate of the upper left corner of the updated rectangle + @param w The width of the updated rectangle + @param h The heigth of the updated rectangle + */ +typedef void (*GotFrameBufferUpdateProc)(struct _rfbClient* client, int x, int y, int w, int h); +/** + Callback indicating that a client has completely processed an rfbFramebufferUpdate + message sent by a server. + This is called exactly once per each handled rfbFramebufferUpdate message. + @param client The client which finished processing an rfbFramebufferUpdate + */ +typedef void (*FinishedFrameBufferUpdateProc)(struct _rfbClient* client); +typedef char* (*GetPasswordProc)(struct _rfbClient* client); +typedef rfbCredential* (*GetCredentialProc)(struct _rfbClient* client, int credentialType); +typedef rfbBool (*MallocFrameBufferProc)(struct _rfbClient* client); +typedef void (*GotXCutTextProc)(struct _rfbClient* client, const char *text, int textlen); +typedef void (*BellProc)(struct _rfbClient* client); +/** + Called when a cursor shape update was received from the server. The decoded cursor shape + will be in client->rcSource. It's up to the application to do something with this, e.g. draw + into a viewer's window. If you want the server to draw the cursor into the framebuffer, be + careful not to announce remote cursor support, i.e. not include rfbEncodingXCursor or + rfbEncodingRichCursor in SetFormatAndEncodings(). +*/ +typedef void (*GotCursorShapeProc)(struct _rfbClient* client, int xhot, int yhot, int width, int height, int bytesPerPixel); +typedef void (*GotCopyRectProc)(struct _rfbClient* client, int src_x, int src_y, int w, int h, int dest_x, int dest_y); +typedef void (*GotFillRectProc)(struct _rfbClient* client, int x, int y, int w, int h, uint32_t colour); +typedef void (*GotBitmapProc)(struct _rfbClient* client, const uint8_t* buffer, int x, int y, int w, int h); +typedef rfbBool (*GotJpegProc)(struct _rfbClient* client, const uint8_t* buffer, int length, int x, int y, int w, int h); +typedef rfbBool (*LockWriteToTLSProc)(struct _rfbClient* client); /** @deprecated */ +typedef rfbBool (*UnlockWriteToTLSProc)(struct _rfbClient* client); /** @deprecated */ + +#ifdef LIBVNCSERVER_HAVE_SASL +typedef char* (*GetUserProc)(struct _rfbClient* client); +typedef char* (*GetSASLMechanismProc)(struct _rfbClient* client, char* mechlist); +#endif /* LIBVNCSERVER_HAVE_SASL */ + +typedef struct _rfbClient { + uint8_t* frameBuffer; + int width, height; + + int endianTest; + + AppData appData; + + const char* programName; + char* serverHost; + int serverPort; /**< if -1, then use file recorded by vncrec */ + rfbBool listenSpecified; + int listenPort, flashPort; + + struct { + int x, y, w, h; + } updateRect; + + /** Note that the CoRRE encoding uses this buffer and assumes it is big enough + to hold 255 * 255 * 32 bits -> 260100 bytes. 640*480 = 307200 bytes. + Hextile also assumes it is big enough to hold 16 * 16 * 32 bits. + Tight encoding assumes BUFFER_SIZE is at least 16384 bytes. */ + +#define RFB_BUFFER_SIZE (640*480) + char buffer[RFB_BUFFER_SIZE]; + + /* rfbproto.c */ + + rfbSocket sock; + rfbBool canUseCoRRE; + rfbBool canUseHextile; + char *desktopName; + rfbPixelFormat format; + rfbServerInitMsg si; + + /* sockets.c */ +#define RFB_BUF_SIZE 8192 + char buf[RFB_BUF_SIZE]; + char *bufoutptr; + unsigned int buffered; + + /* The zlib encoding requires expansion/decompression/deflation of the + compressed data in the "buffer" above into another, result buffer. + However, the size of the result buffer can be determined precisely + based on the bitsPerPixel, height and width of the rectangle. We + allocate this buffer one time to be the full size of the buffer. */ + + /* Ultra Encoding uses this buffer too */ + + int ultra_buffer_size; + char *ultra_buffer; + + int raw_buffer_size; + char *raw_buffer; + +#ifdef LIBVNCSERVER_HAVE_LIBZ + z_stream decompStream; + rfbBool decompStreamInited; +#endif + + +#ifdef LIBVNCSERVER_HAVE_LIBZ + /* + * Variables for the ``tight'' encoding implementation. + */ + + /** Separate buffer for compressed data. */ +#define ZLIB_BUFFER_SIZE 30000 + char zlib_buffer[ZLIB_BUFFER_SIZE]; + + /* Four independent compression streams for zlib library. */ + z_stream zlibStream[4]; + rfbBool zlibStreamActive[4]; + + /* Filter stuff. Should be initialized by filter initialization code. */ + rfbBool cutZeros; + int rectWidth, rectColors; + char tightPalette[256*4]; + uint8_t tightPrevRow[2048*3*sizeof(uint16_t)]; + +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + /** JPEG decoder state (obsolete-- do not use). */ + rfbBool jpegError; + + struct jpeg_source_mgr* jpegSrcManager; + void* jpegBufferPtr; + size_t jpegBufferLen; + +#endif +#endif + + + /* cursor.c */ + /** Holds cursor shape data when received from server. */ + uint8_t *rcSource, *rcMask; + + /** private data pointer */ + rfbClientData* clientData; + + rfbVNCRec* vncRec; + + /* Keyboard State support (is 'Caps Lock' set on the remote display???) */ + int KeyboardLedStateEnabled; + int CurrentKeyboardLedState; + + int canHandleNewFBSize; + + /* hooks */ + HandleTextChatProc HandleTextChat; + HandleKeyboardLedStateProc HandleKeyboardLedState; + HandleCursorPosProc HandleCursorPos; + SoftCursorLockAreaProc SoftCursorLockArea; + SoftCursorUnlockScreenProc SoftCursorUnlockScreen; + GotFrameBufferUpdateProc GotFrameBufferUpdate; + /** the pointer returned by GetPassword will be freed after use! */ + GetPasswordProc GetPassword; + MallocFrameBufferProc MallocFrameBuffer; + GotXCutTextProc GotXCutText; + BellProc Bell; + + GotCursorShapeProc GotCursorShape; + GotCopyRectProc GotCopyRect; + + /** Which messages are supported by the server + * This is a *guess* for most servers. + * (If we can even detect the type of server) + * + * If the server supports the "rfbEncodingSupportedMessages" + * then this will be updated when the encoding is received to + * accurately reflect the servers capabilities. + */ + rfbSupportedMessages supportedMessages; + + /** negotiated protocol version */ + int major, minor; + + /** The selected security types */ + uint32_t authScheme, subAuthScheme; + + /** The TLS session for Anonymous TLS and VeNCrypt */ + void* tlsSession; + + /** To support security types that requires user input (except VNC password + * authentication), for example VeNCrypt and MSLogon, this callback function + * must be set before the authentication. Otherwise, it implicates that the + * caller application does not support it and related security types should + * be bypassed. + */ + GetCredentialProc GetCredential; + + /** The 0-terminated security types supported by the client. + * Set by function SetClientAuthSchemes() */ + uint32_t *clientAuthSchemes; + + /** When the server is a repeater, this specifies the final destination */ + char *destHost; + int destPort; + + /** the QoS IP DSCP for this client */ + int QoS_DSCP; + + /** hook to handle xvp server messages */ + HandleXvpMsgProc HandleXvpMsg; + + /* listen.c */ + rfbSocket listenSock; + + FinishedFrameBufferUpdateProc FinishedFrameBufferUpdate; + + char *listenAddress; + /* IPv6 listen socket, address and port*/ + rfbSocket listen6Sock; + char* listen6Address; + int listen6Port; + + /* Output Window ID. When set, client application enables libvncclient to perform direct rendering in its window */ + unsigned long outputWindow; + + /** + * These lock/unlock hooks are not used anymore. LibVNCClient will now use + * platform-specific synchronization library to protect concurrent TLS R/W. + * + * @deprecated + */ + LockWriteToTLSProc LockWriteToTLS; + UnlockWriteToTLSProc UnlockWriteToTLS; + + /** Hooks for custom rendering + * + * VNC rendering boils down to 3 activities: + * - GotCopyRect: copy an area of the framebuffer + * - GotFillRect: fill an area of the framebuffer with a solid color + * - GotBitmap: copy the bitmap in the buffer into the framebuffer + * The client application should either set all three of these or none! + */ + GotFillRectProc GotFillRect; + GotBitmapProc GotBitmap; + /** Hook for custom JPEG decoding and rendering */ + GotJpegProc GotJpeg; + +#ifdef LIBVNCSERVER_HAVE_SASL + sasl_conn_t *saslconn; + const char *saslDecoded; + unsigned int saslDecodedLength; + unsigned int saslDecodedOffset; + sasl_secret_t *saslSecret; + + /* Callback to allow the client to choose a preferred mechanism. The string returned will + be freed once no longer required. */ + GetSASLMechanismProc GetSASLMechanism; + GetUserProc GetUser; + +#endif /* LIBVNCSERVER_HAVE_SASL */ + +#ifdef LIBVNCSERVER_HAVE_LIBZ +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + /** JPEG decoder state. */ + void *tjhnd; + +#endif +#endif + /* timeout in seconds for select() after connect() */ + unsigned int connectTimeout; + + /* timeout in seconds when reading from half-open connections in + * ReadFromRFBServer() - keep at 0 to disable timeout detection and handling */ + unsigned int readTimeout; + + /** + * Mutex to protect concurrent TLS read/write. + * For internal use only. + */ + MUTEX(tlsRwMutex); +} rfbClient; + +/* cursor.c */ +/** + * Handles XCursor and RichCursor shape updates from the server. + * We emulate cursor operating on the frame buffer (that is + * why we call it "software cursor"). This decodes the received cursor + * shape and hands it over to GotCursorShapeProc, if set. + */ +extern rfbBool HandleCursorShape(rfbClient* client,int xhot, int yhot, int width, int height, uint32_t enc); + +/* listen.c */ + +extern void listenForIncomingConnections(rfbClient* viewer); +extern int listenForIncomingConnectionsNoFork(rfbClient* viewer, int usec_timeout); + +/* rfbproto.c */ + +extern rfbBool rfbEnableClientLogging; +typedef void (*rfbClientLogProc)(const char *format, ...); +extern rfbClientLogProc rfbClientLog,rfbClientErr; +extern rfbBool ConnectToRFBServer(rfbClient* client,const char *hostname, int port); +extern rfbBool ConnectToRFBRepeater(rfbClient* client,const char *repeaterHost, int repeaterPort, const char *destHost, int destPort); +extern void SetClientAuthSchemes(rfbClient* client,const uint32_t *authSchemes, int size); +extern rfbBool InitialiseRFBConnection(rfbClient* client); +/** + * Sends format and encoding parameters to the server. Your application can + * modify the 'client' data structure directly. However some changes to this + * structure must be communicated back to the server. For instance, if you + * change the encoding to hextile, the server needs to know that it should send + * framebuffer updates in hextile format. Likewise if you change the pixel + * format of the framebuffer, the server must be notified about this as well. + * Call this function to propagate your changes of the local 'client' structure + * over to the server. + * @li Encoding type + * @li RFB protocol extensions announced via pseudo-encodings + * @li Framebuffer pixel format (like RGB vs ARGB) + * @li Remote cursor support + * @param client The client in which the format or encodings have been changed + * @return true if the format or encodings were sent to the server successfully, + * false otherwise + */ +extern rfbBool SetFormatAndEncodings(rfbClient* client); +extern rfbBool SendIncrementalFramebufferUpdateRequest(rfbClient* client); +/** + * Sends a framebuffer update request to the server. A VNC client may request an + * update from the server at any time. You can also specify which portions of + * the screen you want updated. This can be handy if a pointer is at certain + * location and the user pressed a mouse button, for instance. Then you can + * immediately request an update of the region around the pointer from the + * server. + * @note The coordinate system is a left-handed Cartesian coordinate system with + * the Z axis (unused) pointing out of the screen. Alternately you can think of + * it as a right-handed Cartesian coordinate system with the Z axis pointing + * into the screen. The origin is at the upper left corner of the framebuffer. + * @param client The client through which to send the request + * @param x The horizontal position of the update request rectangle + * @param y The vertical position of the update request rectangle + * @param w The width of the update request rectangle + * @param h The height of the update request rectangle + * @param incremental false: server sends rectangle even if nothing changed. + * true: server only sends changed parts of rectangle. + * @return true if the update request was sent successfully, false otherwise + */ +extern rfbBool SendFramebufferUpdateRequest(rfbClient* client, + int x, int y, int w, int h, + rfbBool incremental); +extern rfbBool SendScaleSetting(rfbClient* client,int scaleSetting); +/** + * Sends a pointer event to the server. A pointer event includes a cursor + * location and a button mask. The button mask indicates which buttons on the + * pointing device are pressed. Each button is represented by a bit in the + * button mask. A 1 indicates the button is pressed while a 0 indicates that it + * is not pressed. You may use these pre-defined button masks by ORing them + * together: rfbButton1Mask, rfbButton2Mask, rfbButton3Mask, rfbButton4Mask + * rfbButton5Mask + * @note The cursor location is relative to the client's framebuffer, not the + * client's screen itself. + * @note The coordinate system is a left-handed Cartesian coordinate system with + * the Z axis (unused) pointing out of the screen. Alternately you can think of + * it as a right-handed Cartesian coordinate system with the Z axis pointing + * into the screen. The origin is at the upper left corner of the screen. + * @param client The client through which to send the pointer event + * @param x the horizontal location of the cursor + * @param y the vertical location of the cursor + * @param buttonMask the button mask indicating which buttons are pressed + * @return true if the pointer event was sent successfully, false otherwise + */ +extern rfbBool SendPointerEvent(rfbClient* client,int x, int y, int buttonMask); +/** + * Sends a key event to the server. If your application is not merely a VNC + * viewer (i.e. it controls the server), you'll want to send the keys that the + * user presses to the server. Use this function to do that. + * @param client The client through which to send the key event + * @param key An rfbKeySym defined in rfb/keysym.h + * @param down true if this was a key down event, false otherwise + * @return true if the key event was send successfully, false otherwise + */ +extern rfbBool SendKeyEvent(rfbClient* client,uint32_t key, rfbBool down); +/** + * The same as SendKeyEvent, except a key code will be sent along with the + * symbol if the server supports extended key events. + * @param client The client through which to send the key event + * @param keysym An rfbKeySym defined in rfb/keysym.h + * @param keycode An XT key code + * @param down true if this was a key down event, false otherwise + * @return true if the extended key event is supported and was sent + * successfully, false otherwise + */ +extern rfbBool SendExtendedKeyEvent(rfbClient* client, uint32_t keysym, uint32_t keycode, rfbBool down); +/** + * Places a string on the server's clipboard. Use this function if you want to + * be able to copy and paste between the server and your application. For + * instance, when your application is notified that the user copied some text + * onto the clipboard, you would call this function to synchronize the server's + * clipboard with your local clipboard. + * @param client The client structure through which to send the client cut text + * message + * @param str The string to send (doesn't need to be NULL terminated) + * @param len The length of the string + * @return true if the client cut message was sent successfully, false otherwise + */ +extern rfbBool SendClientCutText(rfbClient* client,char *str, int len); +/** + * Handles messages from the RFB server. You must call this function + * intermittently so LibVNCClient can parse messages from the server. For + * example, if your app has a draw loop, you could place a call to this + * function within that draw loop. + * @note You must call WaitForMessage() before you call this function. + * @param client The client which will handle the RFB server messages + * @return true if the client was able to handle the RFB server messages, false + * otherwise + */ +extern rfbBool HandleRFBServerMessage(rfbClient* client); + +/** + * Sends a text chat message to the server. + * @param client The client through which to send the message + * @param text The text to send + * @return true if the text was sent successfully, false otherwise + */ +extern rfbBool TextChatSend(rfbClient* client, char *text); +/** + * Opens a text chat window on the server. + * @param client The client through which to send the message + * @return true if the window was opened successfully, false otherwise + */ +extern rfbBool TextChatOpen(rfbClient* client); +/** + * Closes the text chat window on the server. + * @param client The client through which to send the message + * @return true if the window was closed successfully, false otherwise + */ +extern rfbBool TextChatClose(rfbClient* client); +extern rfbBool TextChatFinish(rfbClient* client); +extern rfbBool PermitServerInput(rfbClient* client, int enabled); +extern rfbBool SendXvpMsg(rfbClient* client, uint8_t version, uint8_t code); + +extern void PrintPixelFormat(rfbPixelFormat *format); + +extern rfbBool SupportsClient2Server(rfbClient* client, int messageType); +extern rfbBool SupportsServer2Client(rfbClient* client, int messageType); + +/* client data */ + +/** + * Associates a client data tag with the given pointer. LibVNCClient has + * several events to which you can associate your own handlers. These handlers + * have the client structure as one of their parameters. Sometimes, you may want + * to make data from elsewhere in your application available to these handlers + * without using a global variable. To do this, you call + * rfbClientSetClientData() and associate the data with a tag. Then, your + * handler can call rfbClientGetClientData() and get the a pointer to the data + * associated with that tag. + * @param client The client in which to set the client data + * @param tag A unique tag which identifies the data + * @param data A pointer to the data to associate with the tag + */ +void rfbClientSetClientData(rfbClient* client, void* tag, void* data); +/** + * Returns a pointer to the client data associated with the given tag. See the + * the documentation for rfbClientSetClientData() for a discussion of how you + * can use client data. + * @param client The client from which to get the client data + * @param tag The tag which identifies the client data + * @return a pointer to the client data + */ +void* rfbClientGetClientData(rfbClient* client, void* tag); + +/* protocol extensions */ + +typedef struct _rfbClientProtocolExtension { + int* encodings; + /** returns TRUE if the encoding was handled */ + rfbBool (*handleEncoding)(rfbClient* cl, + rfbFramebufferUpdateRectHeader* rect); + /** returns TRUE if it handled the message */ + rfbBool (*handleMessage)(rfbClient* cl, + rfbServerToClientMsg* message); + struct _rfbClientProtocolExtension* next; + uint32_t const* securityTypes; + /** returns TRUE if it handled the authentication */ + rfbBool (*handleAuthentication)(rfbClient* cl, uint32_t authScheme); +} rfbClientProtocolExtension; + +void rfbClientRegisterExtension(rfbClientProtocolExtension* e); + +/* sockets.c */ + +extern rfbBool errorMessageOnReadFailure; + +extern rfbBool ReadFromRFBServer(rfbClient* client, char *out, unsigned int n); +extern rfbBool WriteToRFBServer(rfbClient* client, const char *buf, unsigned int n); +extern int FindFreeTcpPort(void); +extern rfbSocket ListenAtTcpPort(int port); +extern rfbSocket ListenAtTcpPortAndAddress(int port, const char *address); +/** + Tries to connect to an IPv4 host. + @param host Binary IPv4 address + @param port Port + @return A blocking socket or RFB_INVALID_SOCKET if the connection failed +*/ +extern rfbSocket ConnectClientToTcpAddr(unsigned int host, int port); +/** + Tries to connect to an IPv4 or IPv6 host. + @param hostname A hostname or IP address + @param port Port + @return A blocking socket or RFB_INVALID_SOCKET if the connection failed +*/ +extern rfbSocket ConnectClientToTcpAddr6(const char *hostname, int port); +/** + Tries to connect to a Unix socket. + @param sockFile Path of the socket file + @return A blocking socket or RFB_INVALID_SOCKET if the connection failed +*/ +extern rfbSocket ConnectClientToUnixSock(const char *sockFile); +/** + Tries to connect to an IPv4 host using the given timeout value. + @param host Binary IPv4 address + @param port Port + @param timeout The time in seconds to wait for a connection + @return A nonblocking socket or RFB_INVALID_SOCKET if the connection failed +*/ +extern rfbSocket ConnectClientToTcpAddrWithTimeout(unsigned int host, int port, unsigned int timeout); +/** + Tries to connect to an IPv4 or IPv6 host using the given timeout value. + @param hostname A hostname or IP address + @param port Port + @param timeout The time in seconds to wait for a connection + @return A nonblocking socket or RFB_INVALID_SOCKET if the connection failed +*/ +extern rfbSocket ConnectClientToTcpAddr6WithTimeout(const char *hostname, int port, unsigned int timeout); +/** + Tries to connect to a Unix socket using the given timeout value. + @param sockFile Path of the socket file + @param timeout The time in seconds to wait for a connection + @return A nonblocking socket or RFB_INVALID_SOCKET if the connection failed +*/ +extern rfbSocket ConnectClientToUnixSockWithTimeout(const char *sockFile, unsigned int timeout); +extern rfbSocket AcceptTcpConnection(rfbSocket listenSock); +extern rfbBool SetNonBlocking(rfbSocket sock); +extern rfbBool SetBlocking(rfbSocket sock); +extern rfbBool SetDSCP(rfbSocket sock, int dscp); + +extern rfbBool StringToIPAddr(const char *str, unsigned int *addr); +extern rfbBool SameMachine(rfbSocket sock); +/** + * Waits for an RFB message to arrive from the server. Before handling a message + * with HandleRFBServerMessage(), you must wait for your client to receive one. + * This function blocks until a message is received. You may specify a timeout + * in microseconds. Once this number of microseconds have elapsed, the function + * will return. + * @param client The client to cause to wait until a message is received + * @param usecs The timeout in microseconds + * @return the return value of the underlying select() call + */ +extern int WaitForMessage(rfbClient* client,unsigned int usecs); + +/* vncviewer.c */ +/** + * Allocates and returns a pointer to an rfbClient structure. This will probably + * be the first LibVNCClient function your client code calls. Most libVNCClient + * functions operate on an rfbClient structure, and this function allocates + * memory for that structure. When you're done with the rfbClient structure + * pointer this function returns, you should free the memory rfbGetClient() + * allocated by calling rfbClientCleanup(). + * + * A pixel is one dot on the screen. The number of bytes in a pixel will depend + * on the number of samples in that pixel and the number of bits in each sample. + * A sample represents one of the primary colors in a color model. The RGB + * color model uses red, green, and blue samples respectively. Suppose you + * wanted to use 16-bit RGB color: You would have three samples per pixel (one + * for each primary color), five bits per sample (the quotient of 16 RGB bits + * divided by three samples), and two bytes per pixel (the smallest multiple of + * eight bits in which the 16-bit pixel will fit). If you wanted 32-bit RGB + * color, you would have three samples per pixel again, eight bits per sample + * (since that's how 32-bit color is defined), and four bytes per pixel (the + * smallest multiple of eight bits in which the 32-bit pixel will fit. + * @param bitsPerSample The number of bits in a sample + * @param samplesPerPixel The number of samples in a pixel + * @param bytesPerPixel The number of bytes in a pixel + * @return a pointer to the allocated rfbClient structure + */ +rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel,int bytesPerPixel); +/** + * Initializes the client. The format is {PROGRAM_NAME, [OPTIONS]..., HOST}. This + * function does not initialize the program name if the rfbClient's program + * name is set already. The options are as follows: + * + * + * + * + * + * + * + * + * + * + *
OptionDescription
-listenListen for incoming connections.
-listennoforkListen for incoming connections without forking. + *
-playSet this client to replay a previously recorded session.
-encodingsSet the encodings to use. The next item in the + * argv array is the encodings string, consisting of comma separated encodings like 'tight,ultra,raw'.
-compressSet the compression level. The next item in the + * argv array is the compression level as an integer. Ranges from 0 (lowest) to 9 (highest). + *
-scaleSet the scaling level. The next item in the + * argv array is the scaling level as an integer. The screen will be scaled down by this factor.
-qosdscpSet the Quality of Service Differentiated Services + * Code Point (QoS DSCP). The next item in the argv array is the code point as + * an integer.
-repeaterdestSet a VNC repeater address. The next item in the argv array is + * the repeater's address as a string.
+ * + * The host may include a port number (delimited by a ':'). + * @param client The client to initialize + * @param argc The number of arguments to the initializer + * @param argv The arguments to the initializer as an array of NULL terminated + * strings + * @return true if the client was initialized successfully, false otherwise. + */ +rfbBool rfbInitClient(rfbClient* client,int* argc,char** argv); +/** + * Cleans up the client structure and releases the memory allocated for it. You + * should call this when you're done with the rfbClient structure that you + * allocated with rfbGetClient(). + * @note rfbClientCleanup() does not touch client->frameBuffer. + * @param client The client to clean up + */ +void rfbClientCleanup(rfbClient* client); + +#if(defined __cplusplus) +} +#endif + +/** + * @} + */ + +/** + @page libvncclient_doc LibVNCClient Documentation + @section example_code Example Code + See SDLvncviewer.c for a rather complete client example. +*/ + +#endif diff --git a/rfb/rfbconfig.h b/rfb/rfbconfig.h new file mode 100644 index 0000000..66baca2 --- /dev/null +++ b/rfb/rfbconfig.h @@ -0,0 +1,201 @@ +#ifndef _RFB_RFBCONFIG_H +#define _RFB_RFBCONFIG_H 1 + +/* rfb/rfbconfig.h. Generated automatically by cmake. */ + +/* Enable 24 bit per pixel in native framebuffer */ +#define LIBVNCSERVER_ALLOW24BPP 1 + +/* work around when write() returns ENOENT but does not mean it */ +#define LIBVNCSERVER_ENOENT_WORKAROUND 1 + +/* Define to 1 if you have the header file. */ +#define LIBVNCSERVER_HAVE_DIRENT_H 1 + +/* Define to 1 if you have the header file. */ +#define LIBVNCSERVER_HAVE_ENDIAN_H 1 + +/* Define to 1 if you have the header file. */ +#define LIBVNCSERVER_HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define LIBVNCSERVER_HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the `ftime' function. */ +#define LIBVNCSERVER_HAVE_FTIME 1 + +/* Define to 1 if you have the `gethostbyname' function. */ +#define LIBVNCSERVER_HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the `gethostname' function. */ +#define LIBVNCSERVER_HAVE_GETHOSTNAME 1 + +/* Define to 1 if you have the `inet_ntoa' function. */ +#define LIBVNCSERVER_HAVE_INET_NTOA 1 + +/* Define to 1 if you have the `memmove' function. */ +#define LIBVNCSERVER_HAVE_MEMMOVE 1 + +/* Define to 1 if you have the `memset' function. */ +#define LIBVNCSERVER_HAVE_MEMSET 1 + +/* Define to 1 if you have the `mkfifo' function. */ +#define LIBVNCSERVER_HAVE_MKFIFO 1 + +/* Define to 1 if you have the `select' function. */ +#define LIBVNCSERVER_HAVE_SELECT 1 + +/* Define to 1 if you have the `socket' function. */ +#define LIBVNCSERVER_HAVE_SOCKET 1 + +/* Define to 1 if you have the `strchr' function. */ +#define LIBVNCSERVER_HAVE_STRCHR 1 + +/* Define to 1 if you have the `strcspn' function. */ +#define LIBVNCSERVER_HAVE_STRCSPN 1 + +/* Define to 1 if you have the `strdup' function. */ +#define LIBVNCSERVER_HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror' function. */ +#define LIBVNCSERVER_HAVE_STRERROR 1 + +/* Define to 1 if you have the `strstr' function. */ +#define LIBVNCSERVER_HAVE_STRSTR 1 + +/* Define to 1 if you have the `jpeg' library (-ljpeg). */ +#define LIBVNCSERVER_HAVE_LIBJPEG 1 + +/* Define if you have the `png' library (-lpng). */ +#define LIBVNCSERVER_HAVE_LIBPNG 1 + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#define LIBVNCSERVER_HAVE_LIBPTHREAD 1 + +/* Define to 1 if you have win32 threads. */ +#define LIBVNCSERVER_HAVE_WIN32THREADS 1 + +/* Define to 1 if you have the `z' library (-lz). */ +#define LIBVNCSERVER_HAVE_LIBZ 1 + +/* Define to 1 if you have the `lzo2' library (-llzo2). */ +#define LIBVNCSERVER_HAVE_LZO 1 + +/* Define to 1 if you have the header file. */ +#define LIBVNCSERVER_HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#define LIBVNCSERVER_HAVE_SYS_ENDIAN_H 1 + +/* Define to 1 if you have the header file. */ +#define LIBVNCSERVER_HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define LIBVNCSERVER_HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define LIBVNCSERVER_HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define LIBVNCSERVER_HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#define LIBVNCSERVER_HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have */ +#define LIBVNCSERVER_HAVE_SYS_UIO_H 1 + +/* Define to 1 if you have */ +#define LIBVNCSERVER_HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define LIBVNCSERVER_HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vfork' function. */ +#define LIBVNCSERVER_HAVE_VFORK 1 + +/* Define to 1 if you have the header file. */ +#define LIBVNCSERVER_HAVE_VFORK_H 1 + +/* Define to 1 if you have the `vprintf' function. */ +#define LIBVNCSERVER_HAVE_VPRINTF 1 + +/* Define to 1 if `fork' works. */ +#define LIBVNCSERVER_HAVE_WORKING_FORK 1 + +/* Define to 1 if `vfork' works. */ +#define LIBVNCSERVER_HAVE_WORKING_VFORK 1 + +/* Define to 1 if `mmap' exists. */ +#define LIBVNCSERVER_HAVE_MMAP 1 + +/* Define to 1 if `fork' exists. */ +#define LIBVNCSERVER_HAVE_FORK 1 + +/* Define to 1 if you have the header file. */ +#define LIBVNCSERVER_HAVE_WS2TCPIP_H 1 + +/* Enable IPv6 support */ +#define LIBVNCSERVER_IPv6 1 + +/* Need a typedef for in_addr_t */ +#define LIBVNCSERVER_NEED_INADDR_T 1 + +/* Define to the full name and version of this package. */ +#define LIBVNCSERVER_PACKAGE_STRING "@FULL_PACKAGE_NAME@ @LibVNCServer_VERSION@" + +/* Define to the version of this package. */ +#define LIBVNCSERVER_PACKAGE_VERSION "@LibVNCServer_VERSION@" +#define LIBVNCSERVER_VERSION "@LibVNCServer_VERSION@" +#define LIBVNCSERVER_VERSION_MAJOR "@LibVNCServer_VERSION_MAJOR@" +#define LIBVNCSERVER_VERSION_MINOR "@LibVNCServer_VERSION_MINOR@" +#define LIBVNCSERVER_VERSION_PATCHLEVEL "@LibVNCServer_VERSION_PATCH@" + +/* Define to 1 if libgcrypt is present */ +#define LIBVNCSERVER_HAVE_LIBGCRYPT 1 + +/* Define to 1 if GnuTLS is present */ +#define LIBVNCSERVER_HAVE_GNUTLS 1 + +/* Define to 1 if OpenSSL is present */ +#define LIBVNCSERVER_HAVE_LIBSSL 1 + +/* Define to 1 if Cyrus SASL is present */ +#define LIBVNCSERVER_HAVE_SASL 1 + +/* Define to 1 to build with websockets */ +#define LIBVNCSERVER_WITH_WEBSOCKETS 1 + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +#define LIBVNCSERVER_WORDS_BIGENDIAN 1 + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #define const @CMAKE_CONST@ */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +/* #ifndef __cplusplus */ +/* #define inline @CMAKE_INLINE@ */ +/* #endif */ + +/* Define to `int' if does not define. */ +#define HAVE_LIBVNCSERVER_PID_T 1 +#ifndef HAVE_LIBVNCSERVER_PID_T +typedef int pid_t; +#endif + +/* The type for size_t */ +#define HAVE_LIBVNCSERVER_SIZE_T 1 +#ifndef HAVE_LIBVNCSERVER_SIZE_T +typedef int size_t; +#endif + +/* The type for socklen */ +#define HAVE_LIBVNCSERVER_SOCKLEN_T 1 +#ifndef HAVE_LIBVNCSERVER_SOCKLEN_T +typedef int socklen_t; +#endif + +/* once: _RFB_RFBCONFIG_H */ +#endif diff --git a/rfb/rfbconfig.h.cmakein b/rfb/rfbconfig.h.cmakein new file mode 100644 index 0000000..d50c3c9 --- /dev/null +++ b/rfb/rfbconfig.h.cmakein @@ -0,0 +1,201 @@ +#ifndef _RFB_RFBCONFIG_H +#cmakedefine _RFB_RFBCONFIG_H 1 + +/* rfb/rfbconfig.h. Generated automatically by cmake. */ + +/* Enable 24 bit per pixel in native framebuffer */ +#cmakedefine LIBVNCSERVER_ALLOW24BPP 1 + +/* work around when write() returns ENOENT but does not mean it */ +#cmakedefine LIBVNCSERVER_ENOENT_WORKAROUND 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_DIRENT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_ENDIAN_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#cmakedefine LIBVNCSERVER_HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the `ftime' function. */ +#cmakedefine LIBVNCSERVER_HAVE_FTIME 1 + +/* Define to 1 if you have the `gethostbyname' function. */ +#cmakedefine LIBVNCSERVER_HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the `gethostname' function. */ +#cmakedefine LIBVNCSERVER_HAVE_GETHOSTNAME 1 + +/* Define to 1 if you have the `inet_ntoa' function. */ +#cmakedefine LIBVNCSERVER_HAVE_INET_NTOA 1 + +/* Define to 1 if you have the `memmove' function. */ +#cmakedefine LIBVNCSERVER_HAVE_MEMMOVE 1 + +/* Define to 1 if you have the `memset' function. */ +#cmakedefine LIBVNCSERVER_HAVE_MEMSET 1 + +/* Define to 1 if you have the `mkfifo' function. */ +#cmakedefine LIBVNCSERVER_HAVE_MKFIFO 1 + +/* Define to 1 if you have the `select' function. */ +#cmakedefine LIBVNCSERVER_HAVE_SELECT 1 + +/* Define to 1 if you have the `socket' function. */ +#cmakedefine LIBVNCSERVER_HAVE_SOCKET 1 + +/* Define to 1 if you have the `strchr' function. */ +#cmakedefine LIBVNCSERVER_HAVE_STRCHR 1 + +/* Define to 1 if you have the `strcspn' function. */ +#cmakedefine LIBVNCSERVER_HAVE_STRCSPN 1 + +/* Define to 1 if you have the `strdup' function. */ +#cmakedefine LIBVNCSERVER_HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror' function. */ +#cmakedefine LIBVNCSERVER_HAVE_STRERROR 1 + +/* Define to 1 if you have the `strstr' function. */ +#cmakedefine LIBVNCSERVER_HAVE_STRSTR 1 + +/* Define to 1 if you have the `jpeg' library (-ljpeg). */ +#cmakedefine LIBVNCSERVER_HAVE_LIBJPEG 1 + +/* Define if you have the `png' library (-lpng). */ +#cmakedefine LIBVNCSERVER_HAVE_LIBPNG 1 + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#cmakedefine LIBVNCSERVER_HAVE_LIBPTHREAD 1 + +/* Define to 1 if you have win32 threads. */ +#cmakedefine LIBVNCSERVER_HAVE_WIN32THREADS 1 + +/* Define to 1 if you have the `z' library (-lz). */ +#cmakedefine LIBVNCSERVER_HAVE_LIBZ 1 + +/* Define to 1 if you have the `lzo2' library (-llzo2). */ +#cmakedefine LIBVNCSERVER_HAVE_LZO 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_ENDIAN_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_UIO_H 1 + +/* Define to 1 if you have */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vfork' function. */ +#cmakedefine LIBVNCSERVER_HAVE_VFORK 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_VFORK_H 1 + +/* Define to 1 if you have the `vprintf' function. */ +#cmakedefine LIBVNCSERVER_HAVE_VPRINTF 1 + +/* Define to 1 if `fork' works. */ +#cmakedefine LIBVNCSERVER_HAVE_WORKING_FORK 1 + +/* Define to 1 if `vfork' works. */ +#cmakedefine LIBVNCSERVER_HAVE_WORKING_VFORK 1 + +/* Define to 1 if `mmap' exists. */ +#cmakedefine LIBVNCSERVER_HAVE_MMAP 1 + +/* Define to 1 if `fork' exists. */ +#cmakedefine LIBVNCSERVER_HAVE_FORK 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_WS2TCPIP_H 1 + +/* Enable IPv6 support */ +#cmakedefine LIBVNCSERVER_IPv6 1 + +/* Need a typedef for in_addr_t */ +#cmakedefine LIBVNCSERVER_NEED_INADDR_T 1 + +/* Define to the full name and version of this package. */ +#define LIBVNCSERVER_PACKAGE_STRING "@FULL_PACKAGE_NAME@ @LibVNCServer_VERSION@" + +/* Define to the version of this package. */ +#define LIBVNCSERVER_PACKAGE_VERSION "@LibVNCServer_VERSION@" +#define LIBVNCSERVER_VERSION "@LibVNCServer_VERSION@" +#define LIBVNCSERVER_VERSION_MAJOR "@LibVNCServer_VERSION_MAJOR@" +#define LIBVNCSERVER_VERSION_MINOR "@LibVNCServer_VERSION_MINOR@" +#define LIBVNCSERVER_VERSION_PATCHLEVEL "@LibVNCServer_VERSION_PATCH@" + +/* Define to 1 if libgcrypt is present */ +#cmakedefine LIBVNCSERVER_HAVE_LIBGCRYPT 1 + +/* Define to 1 if GnuTLS is present */ +#cmakedefine LIBVNCSERVER_HAVE_GNUTLS 1 + +/* Define to 1 if OpenSSL is present */ +#cmakedefine LIBVNCSERVER_HAVE_LIBSSL 1 + +/* Define to 1 if Cyrus SASL is present */ +#cmakedefine LIBVNCSERVER_HAVE_SASL 1 + +/* Define to 1 to build with websockets */ +#cmakedefine LIBVNCSERVER_WITH_WEBSOCKETS 1 + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +#cmakedefine LIBVNCSERVER_WORDS_BIGENDIAN 1 + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #cmakedefine const @CMAKE_CONST@ */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +/* #ifndef __cplusplus */ +/* #cmakedefine inline @CMAKE_INLINE@ */ +/* #endif */ + +/* Define to `int' if does not define. */ +#cmakedefine HAVE_LIBVNCSERVER_PID_T 1 +#ifndef HAVE_LIBVNCSERVER_PID_T +typedef int pid_t; +#endif + +/* The type for size_t */ +#cmakedefine HAVE_LIBVNCSERVER_SIZE_T 1 +#ifndef HAVE_LIBVNCSERVER_SIZE_T +typedef int size_t; +#endif + +/* The type for socklen */ +#cmakedefine HAVE_LIBVNCSERVER_SOCKLEN_T 1 +#ifndef HAVE_LIBVNCSERVER_SOCKLEN_T +typedef int socklen_t; +#endif + +/* once: _RFB_RFBCONFIG_H */ +#endif diff --git a/rfb/rfbproto.h b/rfb/rfbproto.h new file mode 100644 index 0000000..c35dbdc --- /dev/null +++ b/rfb/rfbproto.h @@ -0,0 +1,1556 @@ +#ifndef RFBPROTO_H +#define RFBPROTO_H + +/** + @mainpage + @li @ref libvncserver_api + @li @ref libvncserver_doc + + + @li @ref libvncclient_api + @li @ref libvncclient_doc + +*/ + +/* + * Copyright (C) 2009-2010 D. R. Commander. All Rights Reserved. + * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin + * Copyright (C) 2004-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (C) 2000-2002 Constantin Kaplinsky. All Rights Reserved. + * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * rfbproto.h - header file for the RFB protocol version 3.3 + * + * Uses types CARD for an n-bit unsigned integer, INT for an n-bit signed + * integer (for n = 8, 16 and 32). + * + * All multiple byte integers are in big endian (network) order (most + * significant byte first). Unless noted otherwise there is no special + * alignment of protocol structures. + * + * + * Once the initial handshaking is done, all messages start with a type byte, + * (usually) followed by message-specific data. The order of definitions in + * this file is as follows: + * + * (1) Structures used in several types of message. + * (2) Structures used in the initial handshaking. + * (3) Message types. + * (4) Encoding types. + * (5) For each message type, the form of the data following the type byte. + * Sometimes this is defined by a single structure but the more complex + * messages have to be explained by comments. + */ + +#include + +#if defined(WIN32) +typedef int8_t rfbBool; +#include +#include +#endif +#include + +#ifdef LIBVNCSERVER_HAVE_LIBZ +#include +#ifdef __CHECKER__ +#undef Z_NULL +#define Z_NULL NULL +#endif +#endif + +#if LIBVNCSERVER_HAVE_ENDIAN_H +# include +# if __BYTE_ORDER == __BIG_ENDIAN +# define LIBVNCSERVER_WORDS_BIGENDIAN 1 +# endif +#endif + +/* MS compilers don't have strncasecmp */ +#ifdef _MSC_VER +#define strncasecmp _strnicmp +#endif + +#define rfbMax(a,b) (((a)>(b))?(a):(b)) +#ifdef WIN32 +#define rfbSocket SOCKET +#define RFB_INVALID_SOCKET INVALID_SOCKET +#define rfbCloseSocket closesocket +#else +#ifdef LIBVNCSERVER_HAVE_SYS_TIME_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H +#include +#endif +#define rfbSocket int +#define SOCKET int /* LibVNCServer versions older than 0.9.13 defined this for non-Windows, so keep it here */ +#define RFB_INVALID_SOCKET (-1) +#define rfbCloseSocket close +typedef int8_t rfbBool; +#undef FALSE +#define FALSE 0 +#undef TRUE +#define TRUE -1 +#endif + +typedef uint32_t rfbKeySym; +typedef uint32_t rfbPixel; + +#ifdef LIBVNCSERVER_NEED_INADDR_T +typedef uint32_t in_addr_t; +#endif + +#ifndef INADDR_NONE +#define INADDR_NONE ((in_addr_t) 0xffffffff) +#endif + +#define MAX_ENCODINGS 64 + +/***************************************************************************** + * + * Structures used in several messages + * + *****************************************************************************/ + +/*----------------------------------------------------------------------------- + * Structure used to specify a rectangle. This structure is a multiple of 4 + * bytes so that it can be interspersed with 32-bit pixel data without + * affecting alignment. + */ + +typedef struct { + uint16_t x; + uint16_t y; + uint16_t w; + uint16_t h; +} rfbRectangle; + +#define sz_rfbRectangle 8 + + +/*----------------------------------------------------------------------------- + * Structure used to specify pixel format. + */ + +typedef struct { + + uint8_t bitsPerPixel; /* 8,16,32 only */ + + uint8_t depth; /* 8 to 32 */ + + uint8_t bigEndian; /* True if multi-byte pixels are interpreted + as big endian, or if single-bit-per-pixel + has most significant bit of the byte + corresponding to first (leftmost) pixel. Of + course this is meaningless for 8 bits/pix */ + + uint8_t trueColour; /* If false then we need a "colour map" to + convert pixels to RGB. If true, xxxMax and + xxxShift specify bits used for red, green + and blue */ + + /* the following fields are only meaningful if trueColour is true */ + + uint16_t redMax; /* maximum red value (= 2^n - 1 where n is the + number of bits used for red). Note this + value is always in big endian order. */ + + uint16_t greenMax; /* similar for green */ + + uint16_t blueMax; /* and blue */ + + uint8_t redShift; /* number of shifts needed to get the red + value in a pixel to the least significant + bit. To find the red value from a given + pixel, do the following: + 1) Swap pixel value according to bigEndian + (e.g. if bigEndian is false and host byte + order is big endian, then swap). + 2) Shift right by redShift. + 3) AND with redMax (in host byte order). + 4) You now have the red value between 0 and + redMax. */ + + uint8_t greenShift; /* similar for green */ + + uint8_t blueShift; /* and blue */ + + uint8_t pad1; + uint16_t pad2; + +} rfbPixelFormat; + +#define sz_rfbPixelFormat 16 + +/* UltraVNC: Color settings values */ +#define rfbPFFullColors 0 +#define rfbPF256Colors 1 +#define rfbPF64Colors 2 +#define rfbPF8Colors 3 +#define rfbPF8GreyColors 4 +#define rfbPF4GreyColors 5 +#define rfbPF2GreyColors 6 + + +/***************************************************************************** + * + * Initial handshaking messages + * + *****************************************************************************/ + +/*----------------------------------------------------------------------------- + * Protocol Version + * + * The server always sends 12 bytes to start which identifies the latest RFB + * protocol version number which it supports. These bytes are interpreted + * as a string of 12 ASCII characters in the format "RFB xxx.yyy\n" where + * xxx and yyy are the major and minor version numbers (for version 3.3 + * this is "RFB 003.003\n"). + * + * The client then replies with a similar 12-byte message giving the version + * number of the protocol which should actually be used (which may be different + * to that quoted by the server). + * + * It is intended that both clients and servers may provide some level of + * backwards compatibility by this mechanism. Servers in particular should + * attempt to provide backwards compatibility, and even forwards compatibility + * to some extent. For example if a client demands version 3.1 of the + * protocol, a 3.0 server can probably assume that by ignoring requests for + * encoding types it doesn't understand, everything will still work OK. This + * will probably not be the case for changes in the major version number. + * + * The format string below can be used in sprintf or sscanf to generate or + * decode the version string respectively. + */ + +#define rfbProtocolVersionFormat "RFB %03d.%03d\n" +#define rfbProtocolMajorVersion 3 +#define rfbProtocolMinorVersion 8 +/* UltraVNC Viewer examines rfbProtocolMinorVersion number (4, and 6) + * to identify if the server supports File Transfer + */ + +typedef char rfbProtocolVersionMsg[13]; /* allow extra byte for null */ + +#define sz_rfbProtocolVersionMsg 12 + +/* + * Negotiation of the security type (protocol version 3.7) + * + * Once the protocol version has been decided, the server either sends a list + * of supported security types, or informs the client about an error (when the + * number of security types is 0). Security type rfbSecTypeTight is used to + * enable TightVNC-specific protocol extensions. The value rfbSecTypeVncAuth + * stands for classic VNC authentication. + * + * The client selects a particular security type from the list provided by the + * server. + */ + +#define rfbSecTypeInvalid 0 +#define rfbSecTypeNone 1 +#define rfbSecTypeVncAuth 2 + + +/*----------------------------------------------------------------------------- + * Authentication + * + * Once the protocol version has been decided, the server then sends a 32-bit + * word indicating whether any authentication is needed on the connection. + * The value of this word determines the authentication scheme in use. For + * version 3.0 of the protocol this may have one of the following values: + */ + +#define rfbConnFailed 0 +#define rfbNoAuth 1 +#define rfbVncAuth 2 + +#define rfbRA2 5 +#define rfbRA2ne 6 +#define rfbSSPI 7 +#define rfbSSPIne 8 +#define rfbTight 16 +#define rfbUltra 17 +#define rfbTLS 18 +#define rfbVeNCrypt 19 +#define rfbSASL 20 +#define rfbARD 30 +#define rfbUltraMSLogonI 0x70 /* UNIMPLEMENTED */ +#define rfbUltraMSLogonII 0x71 +#define rfbMSLogon 0xfffffffa + +#define rfbVeNCryptPlain 256 +#define rfbVeNCryptTLSNone 257 +#define rfbVeNCryptTLSVNC 258 +#define rfbVeNCryptTLSPlain 259 +#define rfbVeNCryptX509None 260 +#define rfbVeNCryptX509VNC 261 +#define rfbVeNCryptX509Plain 262 +#define rfbVeNCryptX509SASL 263 +#define rfbVeNCryptTLSSASL 264 + +/* + * rfbConnFailed: For some reason the connection failed (e.g. the server + * cannot support the desired protocol version). This is + * followed by a string describing the reason (where a + * string is specified as a 32-bit length followed by that + * many ASCII characters). + * + * rfbNoAuth: No authentication is needed. + * + * rfbVncAuth: The VNC authentication scheme is to be used. A 16-byte + * challenge follows, which the client encrypts as + * appropriate using the password and sends the resulting + * 16-byte response. If the response is correct, the + * server sends the 32-bit word rfbVncAuthOK. If a simple + * failure happens, the server sends rfbVncAuthFailed and + * closes the connection. If the server decides that too + * many failures have occurred, it sends rfbVncAuthTooMany + * and closes the connection. In the latter case, the + * server should not allow an immediate reconnection by + * the client. + */ + +#define rfbVncAuthOK 0 +#define rfbVncAuthFailed 1 +#define rfbVncAuthTooMany 2 + + +/*----------------------------------------------------------------------------- + * Client Initialisation Message + * + * Once the client and server are sure that they're happy to talk to one + * another, the client sends an initialisation message. At present this + * message only consists of a boolean indicating whether the server should try + * to share the desktop by leaving other clients connected, or give exclusive + * access to this client by disconnecting all other clients. + */ + +typedef struct { + uint8_t shared; +} rfbClientInitMsg; + +#define sz_rfbClientInitMsg 1 + + +/*----------------------------------------------------------------------------- + * Server Initialisation Message + * + * After the client initialisation message, the server sends one of its own. + * This tells the client the width and height of the server's framebuffer, + * its pixel format and the name associated with the desktop. + */ + +typedef struct { + uint16_t framebufferWidth; + uint16_t framebufferHeight; + rfbPixelFormat format; /* the server's preferred pixel format */ + uint32_t nameLength; + /* followed by char name[nameLength] */ +} rfbServerInitMsg; + +#define sz_rfbServerInitMsg (8 + sz_rfbPixelFormat) + + +/* + * Following the server initialisation message it's up to the client to send + * whichever protocol messages it wants. Typically it will send a + * SetPixelFormat message and a SetEncodings message, followed by a + * FramebufferUpdateRequest. From then on the server will send + * FramebufferUpdate messages in response to the client's + * FramebufferUpdateRequest messages. The client should send + * FramebufferUpdateRequest messages with incremental set to true when it has + * finished processing one FramebufferUpdate and is ready to process another. + * With a fast client, the rate at which FramebufferUpdateRequests are sent + * should be regulated to avoid hogging the network. + */ + + + +/***************************************************************************** + * + * Message types + * + *****************************************************************************/ + +/* server -> client */ + +#define rfbFramebufferUpdate 0 +#define rfbSetColourMapEntries 1 +#define rfbBell 2 +#define rfbServerCutText 3 +/* Modif sf@2002 */ +#define rfbResizeFrameBuffer 4 +#define rfbPalmVNCReSizeFrameBuffer 0xF + +/* client -> server */ + +#define rfbSetPixelFormat 0 +#define rfbFixColourMapEntries 1 /* not currently supported */ +#define rfbSetEncodings 2 +#define rfbFramebufferUpdateRequest 3 +#define rfbKeyEvent 4 +#define rfbPointerEvent 5 +#define rfbClientCutText 6 +/* Modif sf@2002 - actually bidirectionnal */ +#define rfbFileTransfer 7 +/* Modif sf@2002 */ +#define rfbSetScale 8 +/* Modif rdv@2002 */ +#define rfbSetServerInput 9 +/* Modif rdv@2002 */ +#define rfbSetSW 10 +/* Modif sf@2002 - TextChat - Bidirectionnal */ +#define rfbTextChat 11 +/* Modif cs@2005 */ +/* PalmVNC 1.4 & 2.0 SetScale Factor message */ +#define rfbPalmVNCSetScaleFactor 0xF +/* Xvp message - bidirectional */ +#define rfbXvp 250 +/* SetDesktopSize client -> server message */ +#define rfbSetDesktopSize 251 +#define rfbQemuEvent 255 + + + + +/***************************************************************************** + * + * Encoding types + * + *****************************************************************************/ + +#define rfbEncodingRaw 0 +#define rfbEncodingCopyRect 1 +#define rfbEncodingRRE 2 +#define rfbEncodingCoRRE 4 +#define rfbEncodingHextile 5 +#define rfbEncodingZlib 6 +#define rfbEncodingTight 7 +#define rfbEncodingTightPng 0xFFFFFEFC /* -260 */ +#define rfbEncodingZlibHex 8 +#define rfbEncodingUltra 9 +#define rfbEncodingTRLE 15 +#define rfbEncodingZRLE 16 +#define rfbEncodingZYWRLE 17 + +#define rfbEncodingH264 0x48323634 + +/* Cache & XOR-Zlib - rdv@2002 */ +#define rfbEncodingCache 0xFFFF0000 +#define rfbEncodingCacheEnable 0xFFFF0001 +#define rfbEncodingXOR_Zlib 0xFFFF0002 +#define rfbEncodingXORMonoColor_Zlib 0xFFFF0003 +#define rfbEncodingXORMultiColor_Zlib 0xFFFF0004 +#define rfbEncodingSolidColor 0xFFFF0005 +#define rfbEncodingXOREnable 0xFFFF0006 +#define rfbEncodingCacheZip 0xFFFF0007 +#define rfbEncodingSolMonoZip 0xFFFF0008 +#define rfbEncodingUltraZip 0xFFFF0009 + +/* Xvp pseudo-encoding */ +#define rfbEncodingXvp 0xFFFFFECB + +/* + * Special encoding numbers: + * 0xFFFFFD00 .. 0xFFFFFD05 -- subsampling level + * 0xFFFFFE00 .. 0xFFFFFE64 -- fine-grained quality level (0-100 scale) + * 0xFFFFFF00 .. 0xFFFFFF0F -- encoding-specific compression levels; + * 0xFFFFFF10 .. 0xFFFFFF1F -- mouse cursor shape data; + * 0xFFFFFF20 .. 0xFFFFFF2F -- various protocol extensions; + * 0xFFFFFF30 .. 0xFFFFFFDF -- not allocated yet; + * 0xFFFFFFE0 .. 0xFFFFFFEF -- quality level for JPEG compressor; + * 0xFFFFFFF0 .. 0xFFFFFFFF -- cross-encoding compression levels. + */ + +#define rfbEncodingFineQualityLevel0 0xFFFFFE00 +#define rfbEncodingFineQualityLevel100 0xFFFFFE64 +#define rfbEncodingSubsamp1X 0xFFFFFD00 +#define rfbEncodingSubsamp4X 0xFFFFFD01 +#define rfbEncodingSubsamp2X 0xFFFFFD02 +#define rfbEncodingSubsampGray 0xFFFFFD03 +#define rfbEncodingSubsamp8X 0xFFFFFD04 +#define rfbEncodingSubsamp16X 0xFFFFFD05 + +#define rfbEncodingCompressLevel0 0xFFFFFF00 +#define rfbEncodingCompressLevel1 0xFFFFFF01 +#define rfbEncodingCompressLevel2 0xFFFFFF02 +#define rfbEncodingCompressLevel3 0xFFFFFF03 +#define rfbEncodingCompressLevel4 0xFFFFFF04 +#define rfbEncodingCompressLevel5 0xFFFFFF05 +#define rfbEncodingCompressLevel6 0xFFFFFF06 +#define rfbEncodingCompressLevel7 0xFFFFFF07 +#define rfbEncodingCompressLevel8 0xFFFFFF08 +#define rfbEncodingCompressLevel9 0xFFFFFF09 + +#define rfbEncodingXCursor 0xFFFFFF10 +#define rfbEncodingRichCursor 0xFFFFFF11 +#define rfbEncodingPointerPos 0xFFFFFF18 + +#define rfbEncodingLastRect 0xFFFFFF20 +#define rfbEncodingNewFBSize 0xFFFFFF21 +#define rfbEncodingExtDesktopSize 0xFFFFFECC + +#define rfbEncodingQualityLevel0 0xFFFFFFE0 +#define rfbEncodingQualityLevel1 0xFFFFFFE1 +#define rfbEncodingQualityLevel2 0xFFFFFFE2 +#define rfbEncodingQualityLevel3 0xFFFFFFE3 +#define rfbEncodingQualityLevel4 0xFFFFFFE4 +#define rfbEncodingQualityLevel5 0xFFFFFFE5 +#define rfbEncodingQualityLevel6 0xFFFFFFE6 +#define rfbEncodingQualityLevel7 0xFFFFFFE7 +#define rfbEncodingQualityLevel8 0xFFFFFFE8 +#define rfbEncodingQualityLevel9 0xFFFFFFE9 + +#define rfbEncodingQemuExtendedKeyEvent 0xFFFFFEFE /* -258 */ +#define rfbEncodingExtendedClipboard 0xC0A1E5CE + +/* LibVNCServer additions. We claim 0xFFFE0000 - 0xFFFE00FF */ +#define rfbEncodingKeyboardLedState 0xFFFE0000 +#define rfbEncodingSupportedMessages 0xFFFE0001 +#define rfbEncodingSupportedEncodings 0xFFFE0002 +#define rfbEncodingServerIdentity 0xFFFE0003 + + +/***************************************************************************** + * + * Server -> client message definitions + * + *****************************************************************************/ + + +/*----------------------------------------------------------------------------- + * FramebufferUpdate - a block of rectangles to be copied to the framebuffer. + * + * This message consists of a header giving the number of rectangles of pixel + * data followed by the rectangles themselves. The header is padded so that + * together with the type byte it is an exact multiple of 4 bytes (to help + * with alignment of 32-bit pixels): + */ + +typedef struct { + uint8_t type; /* always rfbFramebufferUpdate */ + uint8_t pad; + uint16_t nRects; + /* followed by nRects rectangles */ +} rfbFramebufferUpdateMsg; + +#define sz_rfbFramebufferUpdateMsg 4 + +/* + * Each rectangle of pixel data consists of a header describing the position + * and size of the rectangle and a type word describing the encoding of the + * pixel data, followed finally by the pixel data. Note that if the client has + * not sent a SetEncodings message then it will only receive raw pixel data. + * Also note again that this structure is a multiple of 4 bytes. + */ + +typedef struct { + rfbRectangle r; + uint32_t encoding; /* one of the encoding types rfbEncoding... */ +} rfbFramebufferUpdateRectHeader; + +#define sz_rfbFramebufferUpdateRectHeader (sz_rfbRectangle + 4) + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Supported Messages Encoding. This encoding does not contain any pixel data. + * Instead, it contains 2 sets of bitflags. These bitflags indicate what messages + * are supported by the server. + * rect->w contains byte count + */ + +typedef struct { + uint8_t client2server[32]; /* maximum of 256 message types (256/8)=32 */ + uint8_t server2client[32]; /* maximum of 256 message types (256/8)=32 */ +} rfbSupportedMessages; + +#define sz_rfbSupportedMessages 64 + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Supported Encodings Encoding. This encoding does not contain any pixel data. + * Instead, it contains a list of (uint32_t) Encodings supported by this server. + * rect->w contains byte count + * rect->h contains encoding count + */ + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Server Identity Encoding. This encoding does not contain any pixel data. + * Instead, it contains a text string containing information about the server. + * ie: "x11vnc: 0.8.1 lastmod: 2006-04-25 (libvncserver 0.9pre)\0" + * rect->w contains byte count + */ + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Raw Encoding. Pixels are sent in top-to-bottom scanline order, + * left-to-right within a scanline with no padding in between. + */ + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * KeyboardLedState Encoding. The X coordinate contains the Locked Modifiers + * so that a remote troubleshooter can identify that the users 'Caps Lock' + * is set... (It helps a *lot* when the users are untrained) + */ +#define rfbKeyboardMaskShift 1 +#define rfbKeyboardMaskCapsLock 2 +#define rfbKeyboardMaskControl 4 +#define rfbKeyboardMaskAlt 8 +#define rfbKeyboardMaskMeta 16 +#define rfbKeyboardMaskSuper 32 +#define rfbKeyboardMaskHyper 64 +#define rfbKeyboardMaskNumLock 128 +#define rfbKeyboardMaskScrollLock 256 +#define rfbKeyboardMaskAltGraph 512 + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * CopyRect Encoding. The pixels are specified simply by the x and y position + * of the source rectangle. + */ + +typedef struct { + uint16_t srcX; + uint16_t srcY; +} rfbCopyRect; + +#define sz_rfbCopyRect 4 + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * RRE - Rise-and-Run-length Encoding. We have an rfbRREHeader structure + * giving the number of subrectangles following. Finally the data follows in + * the form [...] where each is + * []. + */ + +typedef struct { + uint32_t nSubrects; +} rfbRREHeader; + +#define sz_rfbRREHeader 4 + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * CoRRE - Compact RRE Encoding. We have an rfbRREHeader structure giving + * the number of subrectangles following. Finally the data follows in the form + * [...] where each is + * []. This means that + * the whole rectangle must be at most 255x255 pixels. + */ + +typedef struct { + uint8_t x; + uint8_t y; + uint8_t w; + uint8_t h; +} rfbCoRRERectangle; + +#define sz_rfbCoRRERectangle 4 + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Hextile Encoding. The rectangle is divided up into "tiles" of 16x16 pixels, + * starting at the top left going in left-to-right, top-to-bottom order. If + * the width of the rectangle is not an exact multiple of 16 then the width of + * the last tile in each row will be correspondingly smaller. Similarly if the + * height is not an exact multiple of 16 then the height of each tile in the + * final row will also be smaller. Each tile begins with a "subencoding" type + * byte, which is a mask made up of a number of bits. If the Raw bit is set + * then the other bits are irrelevant; w*h pixel values follow (where w and h + * are the width and height of the tile). Otherwise the tile is encoded in a + * similar way to RRE, except that the position and size of each subrectangle + * can be specified in just two bytes. The other bits in the mask are as + * follows: + * + * BackgroundSpecified - if set, a pixel value follows which specifies + * the background colour for this tile. The first non-raw tile in a + * rectangle must have this bit set. If this bit isn't set then the + * background is the same as the last tile. + * + * ForegroundSpecified - if set, a pixel value follows which specifies + * the foreground colour to be used for all subrectangles in this tile. + * If this bit is set then the SubrectsColoured bit must be zero. + * + * AnySubrects - if set, a single byte follows giving the number of + * subrectangles following. If not set, there are no subrectangles (i.e. + * the whole tile is just solid background colour). + * + * SubrectsColoured - if set then each subrectangle is preceded by a pixel + * value giving the colour of that subrectangle. If not set, all + * subrectangles are the same colour, the foreground colour; if the + * ForegroundSpecified bit wasn't set then the foreground is the same as + * the last tile. + * + * The position and size of each subrectangle is specified in two bytes. The + * Pack macros below can be used to generate the two bytes from x, y, w, h, + * and the Extract macros can be used to extract the x, y, w, h values from + * the two bytes. + */ + +#define rfbHextileRaw (1 << 0) +#define rfbHextileBackgroundSpecified (1 << 1) +#define rfbHextileForegroundSpecified (1 << 2) +#define rfbHextileAnySubrects (1 << 3) +#define rfbHextileSubrectsColoured (1 << 4) + +#define rfbHextilePackXY(x,y) (((x) << 4) | (y)) +#define rfbHextilePackWH(w,h) ((((w)-1) << 4) | ((h)-1)) +#define rfbHextileExtractX(byte) ((byte) >> 4) +#define rfbHextileExtractY(byte) ((byte) & 0xf) +#define rfbHextileExtractW(byte) (((byte) >> 4) + 1) +#define rfbHextileExtractH(byte) (((byte) & 0xf) + 1) + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * zlib - zlib compressed Encoding. We have an rfbZlibHeader structure + * giving the number of bytes following. Finally the data follows is + * zlib compressed version of the raw pixel data as negotiated. + * (NOTE: also used by Ultra Encoding) + */ + +typedef struct { + uint32_t nBytes; +} rfbZlibHeader; + +#define sz_rfbZlibHeader 4 + +#ifdef LIBVNCSERVER_HAVE_LIBZ + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Tight and TightPng Encoding. + * + *-- TightPng is like Tight but basic compression is not used, instead PNG + * data is sent. + * + *-- The first byte of each Tight-encoded rectangle is a "compression control + * byte". Its format is as follows (bit 0 is the least significant one): + * + * bit 0: if 1, then compression stream 0 should be reset; + * bit 1: if 1, then compression stream 1 should be reset; + * bit 2: if 1, then compression stream 2 should be reset; + * bit 3: if 1, then compression stream 3 should be reset; + * bits 7-4: if 1000 (0x08), then the compression type is "fill", + * if 1001 (0x09), then the compression type is "jpeg", + * (Tight only) if 1010 (0x0A), then the compression type is + * "basic" and no Zlib compression was used, + * (Tight only) if 1110 (0x0E), then the compression type is + * "basic", no Zlib compression was used, and a "filter id" byte + * follows this byte, + * (TightPng only) if 1010 (0x0A), then the compression type is + * "png", + * if 0xxx, then the compression type is "basic" and Zlib + * compression was used, + * values greater than 1010 are not valid. + * + * If the compression type is "basic" and Zlib compression was used, then bits + * 6..4 of the compression control byte (those xxx in 0xxx) specify the + * following: + * + * bits 5-4: decimal representation is the index of a particular zlib + * stream which should be used for decompressing the data; + * bit 6: if 1, then a "filter id" byte is following this byte. + * + *-- The data that follows after the compression control byte described + * above depends on the compression type ("fill", "jpeg", "png" or "basic"). + * + *-- If the compression type is "fill", then the only pixel value follows, in + * client pixel format (see NOTE 1). This value applies to all pixels of the + * rectangle. + * + *-- If the compression type is "jpeg" or "png", the following data stream + * looks like this: + * + * 1..3 bytes: data size (N) in compact representation; + * N bytes: JPEG or PNG image. + * + * Data size is compactly represented in one, two or three bytes, according + * to the following scheme: + * + * 0xxxxxxx (for values 0..127) + * 1xxxxxxx 0yyyyyyy (for values 128..16383) + * 1xxxxxxx 1yyyyyyy zzzzzzzz (for values 16384..4194303) + * + * Here each character denotes one bit, xxxxxxx are the least significant 7 + * bits of the value (bits 0-6), yyyyyyy are bits 7-13, and zzzzzzzz are the + * most significant 8 bits (bits 14-21). For example, decimal value 10000 + * should be represented as two bytes: binary 10010000 01001110, or + * hexadecimal 90 4E. + * + *-- If the compression type is "basic" and bit 6 of the compression control + * byte was set to 1, then the next (second) byte specifies "filter id" which + * tells the decoder what filter type was used by the encoder to pre-process + * pixel data before the compression. The "filter id" byte can be one of the + * following: + * + * 0: no filter ("copy" filter); + * 1: "palette" filter; + * 2: "gradient" filter. + * + *-- If bit 6 of the compression control byte is set to 0 (no "filter id" + * byte), or if the filter id is 0, then raw pixel values in the client + * format (see NOTE 1) will be compressed. See below details on the + * compression. + * + *-- The "gradient" filter pre-processes pixel data with a simple algorithm + * which converts each color component to a difference between a "predicted" + * intensity and the actual intensity. Such a technique does not affect + * uncompressed data size, but helps to compress photo-like images better. + * Pseudo-code for converting intensities to differences is the following: + * + * P[i,j] := V[i-1,j] + V[i,j-1] - V[i-1,j-1]; + * if (P[i,j] < 0) then P[i,j] := 0; + * if (P[i,j] > MAX) then P[i,j] := MAX; + * D[i,j] := V[i,j] - P[i,j]; + * + * Here V[i,j] is the intensity of a color component for a pixel at + * coordinates (i,j). MAX is the maximum value of intensity for a color + * component. + * + *-- The "palette" filter converts true-color pixel data to indexed colors + * and a palette which can consist of 2..256 colors. If the number of colors + * is 2, then each pixel is encoded in 1 bit, otherwise 8 bits is used to + * encode one pixel. 1-bit encoding is performed such way that the most + * significant bits correspond to the leftmost pixels, and each raw of pixels + * is aligned to the byte boundary. When "palette" filter is used, the + * palette is sent before the pixel data. The palette begins with an unsigned + * byte which value is the number of colors in the palette minus 1 (i.e. 1 + * means 2 colors, 255 means 256 colors in the palette). Then follows the + * palette itself which consist of pixel values in client pixel format (see + * NOTE 1). + * + *-- The pixel data is compressed using the zlib library. But if the data + * size after applying the filter but before the compression is less then 12, + * then the data is sent as is, uncompressed. Four separate zlib streams + * (0..3) can be used and the decoder should read the actual stream id from + * the compression control byte (see NOTE 2). + * + * If the compression is not used, then the pixel data is sent as is, + * otherwise the data stream looks like this: + * + * 1..3 bytes: data size (N) in compact representation; + * N bytes: zlib-compressed data. + * + * Data size is compactly represented in one, two or three bytes, just like + * in the "jpeg" compression method (see above). + * + *-- NOTE 1. If the color depth is 24, and all three color components are + * 8-bit wide, then one pixel in Tight encoding is always represented by + * three bytes, where the first byte is red component, the second byte is + * green component, and the third byte is blue component of the pixel color + * value. This applies to colors in palettes as well. + * + *-- NOTE 2. The decoder must reset compression streams' states before + * decoding the rectangle, if some of bits 0,1,2,3 in the compression control + * byte are set to 1. Note that the decoder must reset zlib streams even if + * the compression type is "fill", "jpeg" or "png". + * + *-- NOTE 3. The "gradient" filter and "jpeg" compression may be used only + * when bits-per-pixel value is either 16 or 32, not 8. + * + *-- NOTE 4. The width of any Tight-encoded rectangle cannot exceed 2048 + * pixels. If a rectangle is wider, it must be split into several rectangles + * and each one should be encoded separately. + * + */ + +#define rfbTightExplicitFilter 0x04 +#define rfbTightFill 0x08 +#define rfbTightJpeg 0x09 +#define rfbTightNoZlib 0x0A +#define rfbTightPng 0x0A +#define rfbTightMaxSubencoding 0x0A + +/* Filters to improve compression efficiency */ +#define rfbTightFilterCopy 0x00 +#define rfbTightFilterPalette 0x01 +#define rfbTightFilterGradient 0x02 + +#endif + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * XCursor encoding. This is a special encoding used to transmit X-style + * cursor shapes from server to clients. Note that for this encoding, + * coordinates in rfbFramebufferUpdateRectHeader structure hold hotspot + * position (r.x, r.y) and cursor size (r.w, r.h). If (w * h != 0), two RGB + * samples are sent after header in the rfbXCursorColors structure. They + * denote foreground and background colors of the cursor. If a client + * supports only black-and-white cursors, it should ignore these colors and + * assume that foreground is black and background is white. Next, two bitmaps + * (1 bits per pixel) follow: first one with actual data (value 0 denotes + * background color, value 1 denotes foreground color), second one with + * transparency data (bits with zero value mean that these pixels are + * transparent). Both bitmaps represent cursor data in a byte stream, from + * left to right, from top to bottom, and each row is byte-aligned. Most + * significant bits correspond to leftmost pixels. The number of bytes in + * each row can be calculated as ((w + 7) / 8). If (w * h == 0), cursor + * should be hidden (or default local cursor should be set by the client). + */ + +typedef struct { + uint8_t foreRed; + uint8_t foreGreen; + uint8_t foreBlue; + uint8_t backRed; + uint8_t backGreen; + uint8_t backBlue; +} rfbXCursorColors; + +#define sz_rfbXCursorColors 6 + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * RichCursor encoding. This is a special encoding used to transmit cursor + * shapes from server to clients. It is similar to the XCursor encoding but + * uses client pixel format instead of two RGB colors to represent cursor + * image. For this encoding, coordinates in rfbFramebufferUpdateRectHeader + * structure hold hotspot position (r.x, r.y) and cursor size (r.w, r.h). + * After header, two pixmaps follow: first one with cursor image in current + * client pixel format (like in raw encoding), second with transparency data + * (1 bit per pixel, exactly the same format as used for transparency bitmap + * in the XCursor encoding). If (w * h == 0), cursor should be hidden (or + * default local cursor should be set by the client). + */ + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * ZRLE - encoding combining Zlib compression, tiling, palettisation and + * run-length encoding. + */ + +typedef struct { + uint32_t length; +} rfbZRLEHeader; + +#define sz_rfbZRLEHeader 4 + +#define rfbZRLETileWidth 64 +#define rfbZRLETileHeight 64 + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * ZLIBHEX - zlib compressed Hextile Encoding. Essentially, this is the + * hextile encoding with zlib compression on the tiles that can not be + * efficiently encoded with one of the other hextile subencodings. The + * new zlib subencoding uses two bytes to specify the length of the + * compressed tile and then the compressed data follows. As with the + * raw sub-encoding, the zlib subencoding invalidates the other + * values, if they are also set. + */ + +#define rfbHextileZlibRaw (1 << 5) +#define rfbHextileZlibHex (1 << 6) +#define rfbHextileZlibMono (1 << 7) + + +/*----------------------------------------------------------------------------- + * SetColourMapEntries - these messages are only sent if the pixel + * format uses a "colour map" (i.e. trueColour false) and the client has not + * fixed the entire colour map using FixColourMapEntries. In addition they + * will only start being sent after the client has sent its first + * FramebufferUpdateRequest. So if the client always tells the server to use + * trueColour then it never needs to process this type of message. + */ + +typedef struct { + uint8_t type; /* always rfbSetColourMapEntries */ + uint8_t pad; + uint16_t firstColour; + uint16_t nColours; + + /* Followed by nColours * 3 * uint16_t + r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */ + +} rfbSetColourMapEntriesMsg; + +#define sz_rfbSetColourMapEntriesMsg 6 + + + +/*----------------------------------------------------------------------------- + * Bell - ring a bell on the client if it has one. + */ + +typedef struct { + uint8_t type; /* always rfbBell */ +} rfbBellMsg; + +#define sz_rfbBellMsg 1 + + + +/*----------------------------------------------------------------------------- + * ServerCutText - the server has new text in its cut buffer. + */ + +typedef struct { + uint8_t type; /* always rfbServerCutText */ + uint8_t pad1; + uint16_t pad2; + uint32_t length; + /* followed by char text[length] */ +} rfbServerCutTextMsg; + +#define sz_rfbServerCutTextMsg 8 + + +/*----------------------------------------------------------------------------- + * // Modif sf@2002 + * FileTransferMsg - The client sends FileTransfer message. + * Bidirectional message - Files can be sent from client to server & vice versa + */ + +typedef struct _rfbFileTransferMsg { + uint8_t type; /* always rfbFileTransfer */ + uint8_t contentType; /* See defines below */ + uint8_t contentParam;/* Other possible content classification (Dir or File name, etc..) */ + uint8_t pad; /* It appears that UltraVNC *forgot* to Swap16IfLE(contentParam) */ + uint32_t size; /* FileSize or packet index or error or other */ +/* uint32_t sizeH; Additional 32Bits params to handle big values. Only for V2 (we want backward compatibility between all V1 versions) */ + uint32_t length; + /* followed by data char text[length] */ +} rfbFileTransferMsg; + +#define sz_rfbFileTransferMsg 12 + +#define rfbFileTransferVersion 2 /* v1 is the old FT version ( <= 1.0.0 RC18 versions) */ + +/* FileTransfer Content types and Params defines */ +#define rfbDirContentRequest 1 /* Client asks for the content of a given Server directory */ +#define rfbDirPacket 2 /* Full directory name or full file name. */ + /* Null content means end of Directory */ +#define rfbFileTransferRequest 3 /* Client asks the server for the transfer of a given file */ +#define rfbFileHeader 4 /* First packet of a file transfer, containing file's features */ +#define rfbFilePacket 5 /* One chunk of the file */ +#define rfbEndOfFile 6 /* End of file transfer (the file has been received or error) */ +#define rfbAbortFileTransfer 7 /* The file transfer must be aborted, whatever the state */ +#define rfbFileTransferOffer 8 /* The client offers to send a file to the server */ +#define rfbFileAcceptHeader 9 /* The server accepts or rejects the file */ +#define rfbCommand 10 /* The Client sends a simple command (File Delete, Dir create etc...) */ +#define rfbCommandReturn 11 /* The Client receives the server's answer about a simple command */ +#define rfbFileChecksums 12 /* The zipped checksums of the destination file (Delta Transfer) */ +#define rfbFileTransferAccess 14 /* Request FileTransfer authorization */ + + /* rfbDirContentRequest client Request - content params */ +#define rfbRDirContent 1 /* Request a Server Directory contents */ +#define rfbRDrivesList 2 /* Request the server's drives list */ +#define rfbRDirRecursiveList 3 /* Request a server directory content recursive sorted list */ +#define rfbRDirRecursiveSize 4 /* Request a server directory content recursive size */ + + /* rfbDirPacket & rfbCommandReturn server Answer - content params */ +#define rfbADirectory 1 /* Reception of a directory name */ +#define rfbAFile 2 /* Reception of a file name */ +#define rfbADrivesList 3 /* Reception of a list of drives */ +#define rfbADirCreate 4 /* Response to a create dir command */ +#define rfbADirDelete 5 /* Response to a delete dir command */ +#define rfbAFileCreate 6 /* Response to a create file command */ +#define rfbAFileDelete 7 /* Response to a delete file command */ +#define rfbAFileRename 8 /* Response to a rename file command */ +#define rfbADirRename 9 /* Response to a rename dir command */ +#define rfbADirRecursiveListItem 10 +#define rfbADirRecursiveSize 11 + + /* rfbCommand Command - content params */ +#define rfbCDirCreate 1 /* Request the server to create the given directory */ +#define rfbCDirDelete 2 /* Request the server to delete the given directory */ +#define rfbCFileCreate 3 /* Request the server to create the given file */ +#define rfbCFileDelete 4 /* Request the server to delete the given file */ +#define rfbCFileRename 5 /* Request the server to rename the given file */ +#define rfbCDirRename 6 /* Request the server to rename the given directory */ + + /* Errors - content params or "size" field */ +#define rfbRErrorUnknownCmd 1 /* Unknown FileTransfer command. */ +#define rfbRErrorCmd 0xFFFFFFFF/* Error when a command fails on remote side (ret in "size" field) */ + +#define sz_rfbBlockSize 8192 /* Size of a File Transfer packet (before compression) */ +#define rfbZipDirectoryPrefix "!UVNCDIR-\0" /* Transferred directory are zipped in a file with this prefix. Must end with "-" */ +#define sz_rfbZipDirectoryPrefix 9 +#define rfbDirPrefix "[ " +#define rfbDirSuffix " ]" + + + +/*----------------------------------------------------------------------------- + * Modif sf@2002 + * TextChatMsg - Utilized to order the TextChat mode on server or client + * Bidirectional message + */ + +typedef struct _rfbTextChatMsg { + uint8_t type; /* always rfbTextChat */ + uint8_t pad1; /* Could be used later as an additionnal param */ + uint16_t pad2; /* Could be used later as text offset, for instance */ + uint32_t length; /* Specific values for Open, close, finished (-1, -2, -3) */ + /* followed by char text[length] */ +} rfbTextChatMsg; + +#define sz_rfbTextChatMsg 8 + +#define rfbTextMaxSize 4096 +#define rfbTextChatOpen 0xFFFFFFFF +#define rfbTextChatClose 0xFFFFFFFE +#define rfbTextChatFinished 0xFFFFFFFD + + +/*----------------------------------------------------------------------------- + * Xvp Message + * Bidirectional message + * A server which supports the xvp extension declares this by sending a message + * with an Xvp_INIT xvp-message-code when it receives a request from the client + * to use the xvp Pseudo-encoding. The server must specify in this message the + * highest xvp-extension-version it supports: the client may assume that the + * server supports all versions from 1 up to this value. The client is then + * free to use any supported version. Currently, only version 1 is defined. + * + * A server which subsequently receives an xvp Client Message requesting an + * operation which it is unable to perform, informs the client of this by + * sending a message with an Xvp_FAIL xvp-message-code, and the same + * xvp-extension-version as included in the client's operation request. + * + * A client supporting the xvp extension sends this to request that the server + * initiate a clean shutdown, clean reboot or abrupt reset of the system whose + * framebuffer the client is displaying. + */ + + +typedef struct { + uint8_t type; /* always rfbXvp */ + uint8_t pad; + uint8_t version; /* xvp extension version */ + uint8_t code; /* xvp message code */ +} rfbXvpMsg; + +#define sz_rfbXvpMsg (4) + +/* server message codes */ +#define rfbXvp_Fail 0 +#define rfbXvp_Init 1 +/* client message codes */ +#define rfbXvp_Shutdown 2 +#define rfbXvp_Reboot 3 +#define rfbXvp_Reset 4 + +/*----------------------------------------------------------------------------- + * ExtendedDesktopSize server -> client message + * + * Informs the client of (re)size of framebuffer, provides information about + * physical screens attached, and lets the client knows it can request + * resolution changes using SetDesktopSize. + */ + +typedef struct rfbExtDesktopSizeMsg { + uint8_t numberOfScreens; + uint8_t pad[3]; + + /* Followed by rfbExtDesktopScreen[numberOfScreens] */ +} rfbExtDesktopSizeMsg; + +typedef struct rfbExtDesktopScreen { + uint32_t id; + uint16_t x; + uint16_t y; + uint16_t width; + uint16_t height; + uint32_t flags; +} rfbExtDesktopScreen; + +#define sz_rfbExtDesktopSizeMsg (4) +#define sz_rfbExtDesktopScreen (16) + +/* x - reason for the change */ +#define rfbExtDesktopSize_GenericChange 0 +#define rfbExtDesktopSize_ClientRequestedChange 1 +#define rfbExtDesktopSize_OtherClientRequestedChange 2 + +/* y - status code for change */ +#define rfbExtDesktopSize_Success 0 +#define rfbExtDesktopSize_ResizeProhibited 1 +#define rfbExtDesktopSize_OutOfResources 2 +#define rfbExtDesktopSize_InvalidScreenLayout 3 + +/*----------------------------------------------------------------------------- + * SetDesktopSize client -> server message + * + * Allows the client to request that the framebuffer and physical screen + * resolutions are changed. + */ + +typedef struct rfbSetDesktopSizeMsg { + uint8_t type; /* always rfbSetDesktopSize */ + uint8_t pad1; + uint16_t width; + uint16_t height; + uint8_t numberOfScreens; + uint8_t pad2; + + /* Followed by rfbExtDesktopScreen[numberOfScreens] */ +} rfbSetDesktopSizeMsg; + +#define sz_rfbSetDesktopSizeMsg (8) + + +/*----------------------------------------------------------------------------- + * Modif sf@2002 + * ResizeFrameBuffer - The Client must change the size of its framebuffer + */ + +typedef struct _rfbResizeFrameBufferMsg { + uint8_t type; /* always rfbResizeFrameBuffer */ + uint8_t pad1; + uint16_t framebufferWidth; /* FrameBuffer width */ + uint16_t framebufferHeigth; /* FrameBuffer height */ +} rfbResizeFrameBufferMsg; + +#define sz_rfbResizeFrameBufferMsg 6 + + +/*----------------------------------------------------------------------------- + * Copyright (C) 2001 Harakan Software + * PalmVNC 1.4 & 2.? ResizeFrameBuffer message + * ReSizeFrameBuffer - tell the RFB client to alter its framebuffer, either + * due to a resize of the server desktop or a client-requested scaling factor. + * The pixel format remains unchanged. + */ + +typedef struct { + uint8_t type; /* always rfbReSizeFrameBuffer */ + uint8_t pad1; + uint16_t desktop_w; /* Desktop width */ + uint16_t desktop_h; /* Desktop height */ + uint16_t buffer_w; /* FrameBuffer width */ + uint16_t buffer_h; /* Framebuffer height */ + uint16_t pad2; + +} rfbPalmVNCReSizeFrameBufferMsg; + +#define sz_rfbPalmVNCReSizeFrameBufferMsg (12) + + + + +/*----------------------------------------------------------------------------- + * Union of all server->client messages. + */ + +typedef union { + uint8_t type; + rfbFramebufferUpdateMsg fu; + rfbSetColourMapEntriesMsg scme; + rfbBellMsg b; + rfbServerCutTextMsg sct; + rfbResizeFrameBufferMsg rsfb; + rfbPalmVNCReSizeFrameBufferMsg prsfb; + rfbFileTransferMsg ft; + rfbTextChatMsg tc; + rfbXvpMsg xvp; + rfbExtDesktopSizeMsg eds; +} rfbServerToClientMsg; + + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * RDV Cache Encoding. + * special is not used at this point, can be used to reset cache or other specials + * just put it to make sure we don't have to change the encoding again. + */ + +typedef struct { + uint16_t special; +} rfbCacheRect; + +#define sz_rfbCacheRect 2 + + + + +/***************************************************************************** + * + * Message definitions (client -> server) + * + *****************************************************************************/ + + +/*----------------------------------------------------------------------------- + * SetPixelFormat - tell the RFB server the format in which the client wants + * pixels sent. + */ + +typedef struct { + uint8_t type; /* always rfbSetPixelFormat */ + uint8_t pad1; + uint16_t pad2; + rfbPixelFormat format; +} rfbSetPixelFormatMsg; + +#define sz_rfbSetPixelFormatMsg (sz_rfbPixelFormat + 4) + + +/*----------------------------------------------------------------------------- + * FixColourMapEntries - when the pixel format uses a "colour map", fix + * read-only colour map entries. + * + * ***************** NOT CURRENTLY SUPPORTED ***************** + */ + +typedef struct { + uint8_t type; /* always rfbFixColourMapEntries */ + uint8_t pad; + uint16_t firstColour; + uint16_t nColours; + + /* Followed by nColours * 3 * uint16_t + r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */ + +} rfbFixColourMapEntriesMsg; + +#define sz_rfbFixColourMapEntriesMsg 6 + + +/*----------------------------------------------------------------------------- + * SetEncodings - tell the RFB server which encoding types we accept. Put them + * in order of preference, if we have any. We may always receive raw + * encoding, even if we don't specify it here. + */ + +typedef struct { + uint8_t type; /* always rfbSetEncodings */ + uint8_t pad; + uint16_t nEncodings; + /* followed by nEncodings * uint32_t encoding types */ +} rfbSetEncodingsMsg; + +#define sz_rfbSetEncodingsMsg 4 + + +/*----------------------------------------------------------------------------- + * FramebufferUpdateRequest - request for a framebuffer update. If incremental + * is true then the client just wants the changes since the last update. If + * false then it wants the whole of the specified rectangle. + */ + +typedef struct { + uint8_t type; /* always rfbFramebufferUpdateRequest */ + uint8_t incremental; + uint16_t x; + uint16_t y; + uint16_t w; + uint16_t h; +} rfbFramebufferUpdateRequestMsg; + +#define sz_rfbFramebufferUpdateRequestMsg 10 + + +/*----------------------------------------------------------------------------- + * KeyEvent - key press or release + * + * Keys are specified using the "keysym" values defined by the X Window System. + * For most ordinary keys, the keysym is the same as the corresponding ASCII + * value. Other common keys are: + * + * BackSpace 0xff08 + * Tab 0xff09 + * Return or Enter 0xff0d + * Escape 0xff1b + * Insert 0xff63 + * Delete 0xffff + * Home 0xff50 + * End 0xff57 + * Page Up 0xff55 + * Page Down 0xff56 + * Left 0xff51 + * Up 0xff52 + * Right 0xff53 + * Down 0xff54 + * F1 0xffbe + * F2 0xffbf + * ... ... + * F12 0xffc9 + * Shift 0xffe1 + * Control 0xffe3 + * Meta 0xffe7 + * Alt 0xffe9 + */ + +typedef struct { + uint8_t type; /* always rfbKeyEvent */ + uint8_t down; /* true if down (press), false if up */ + uint16_t pad; + uint32_t key; /* key is specified as an X keysym */ +} rfbKeyEventMsg; + +#define sz_rfbKeyEventMsg 8 + + +typedef struct { + uint8_t type; /* always rfbQemuEvent */ + uint8_t subtype; /* always 0 */ + uint16_t down; + uint32_t keysym; /* keysym is specified as an X keysym, may be 0 */ + uint32_t keycode; /* keycode is specified as XT key code */ +} rfbQemuExtendedKeyEventMsg; + +#define sz_rfbQemuExtendedKeyEventMsg 12 + + +/*----------------------------------------------------------------------------- + * PointerEvent - mouse/pen move and/or button press. + */ + +typedef struct { + uint8_t type; /* always rfbPointerEvent */ + uint8_t buttonMask; /* bits 0-7 are buttons 1-8, 0=up, 1=down */ + uint16_t x; + uint16_t y; +} rfbPointerEventMsg; + +#define rfbButton1Mask 1 +#define rfbButton2Mask 2 +#define rfbButton3Mask 4 +#define rfbButton4Mask 8 +#define rfbButton5Mask 16 +/* RealVNC 335 method */ +#define rfbWheelUpMask rfbButton4Mask +#define rfbWheelDownMask rfbButton5Mask + +#define sz_rfbPointerEventMsg 6 + + + +/*----------------------------------------------------------------------------- + * ClientCutText - the client has new text in its cut buffer. + */ + +typedef struct { + uint8_t type; /* always rfbClientCutText */ + uint8_t pad1; + uint16_t pad2; + uint32_t length; + /* followed by char text[length] */ +} rfbClientCutTextMsg; + +#define rfbExtendedClipboard_Text 1 +#define rfbExtendedClipboard_RTF 2 +#define rfbExtendedClipboard_HTML 4 +#define rfbExtendedClipboard_DIB 8 +#define rfbExtendedClipboard_Files 16 +#define rfbExtendedClipboard_Caps (1 << 24) +#define rfbExtendedClipboard_Request (1 << 25) +#define rfbExtendedClipboard_Peek (1 << 26) +#define rfbExtendedClipboard_Notify (1 << 27) +#define rfbExtendedClipboard_Provide (1 << 28) +#define sz_rfbClientCutTextMsg 8 + + + +/*----------------------------------------------------------------------------- + * sf@2002 - Set Server Scale + * SetServerScale - Server must change the scale of the client buffer. + */ + +typedef struct _rfbSetScaleMsg { + uint8_t type; /* always rfbSetScale */ + uint8_t scale; /* Scale value 1server messages. + */ + +typedef union { + uint8_t type; + rfbSetPixelFormatMsg spf; + rfbFixColourMapEntriesMsg fcme; + rfbSetEncodingsMsg se; + rfbFramebufferUpdateRequestMsg fur; + rfbKeyEventMsg ke; + rfbPointerEventMsg pe; + rfbClientCutTextMsg cct; + rfbSetScaleMsg ssc; + rfbPalmVNCSetScaleFactorMsg pssf; + rfbSetServerInputMsg sim; + rfbFileTransferMsg ft; + rfbSetSWMsg sw; + rfbTextChatMsg tc; + rfbXvpMsg xvp; + rfbSetDesktopSizeMsg sdm; +} rfbClientToServerMsg; + +/* + * vncauth.h - describes the functions provided by the vncauth library. + */ + +#define MAXPWLEN 8 +#define CHALLENGESIZE 16 + +extern int rfbEncryptAndStorePasswd(char *passwd, char *fname); +extern char *rfbDecryptPasswdFromFile(char *fname); +extern void rfbRandomBytes(unsigned char *bytes); +extern void rfbEncryptBytes(unsigned char *bytes, char *passwd); + + +#endif diff --git a/rfb/rfbregion.h b/rfb/rfbregion.h new file mode 100644 index 0000000..d352dee --- /dev/null +++ b/rfb/rfbregion.h @@ -0,0 +1,65 @@ +#ifndef SRAREGION_H +#define SRAREGION_H + +/* -=- SRA - Simple Region Algorithm + * A simple rectangular region implementation. + * Copyright (c) 2001 James "Wez" Weatherall, Johannes E. Schindelin + */ + +/* -=- sraRect */ + +typedef struct _rect { + int x1; + int y1; + int x2; + int y2; +} sraRect; + +typedef struct sraRegion sraRegion; + +/* -=- Region manipulation functions */ + +extern sraRegion *sraRgnCreate(void); +extern sraRegion *sraRgnCreateRect(int x1, int y1, int x2, int y2); +extern sraRegion *sraRgnCreateRgn(const sraRegion *src); + +extern void sraRgnDestroy(sraRegion *rgn); +extern void sraRgnMakeEmpty(sraRegion *rgn); +extern rfbBool sraRgnAnd(sraRegion *dst, const sraRegion *src); +extern void sraRgnOr(sraRegion *dst, const sraRegion *src); +extern rfbBool sraRgnSubtract(sraRegion *dst, const sraRegion *src); + +extern void sraRgnOffset(sraRegion *dst, int dx, int dy); + +extern rfbBool sraRgnPopRect(sraRegion *region, sraRect *rect, + unsigned long flags); + +extern unsigned long sraRgnCountRects(const sraRegion *rgn); +extern rfbBool sraRgnEmpty(const sraRegion *rgn); + +extern sraRegion *sraRgnBBox(const sraRegion *src); + +/* -=- rectangle iterator */ + +typedef struct sraRectangleIterator { + rfbBool reverseX,reverseY; + int ptrSize,ptrPos; + struct sraSpan** sPtrs; +} sraRectangleIterator; + +extern sraRectangleIterator *sraRgnGetIterator(sraRegion *s); +extern sraRectangleIterator *sraRgnGetReverseIterator(sraRegion *s,rfbBool reverseX,rfbBool reverseY); +extern rfbBool sraRgnIteratorNext(sraRectangleIterator *i,sraRect *r); +extern void sraRgnReleaseIterator(sraRectangleIterator *i); + +void sraRgnPrint(const sraRegion *s); + +/* -=- Rectangle clipper (for speed) */ + +extern rfbBool sraClipRect(int *x, int *y, int *w, int *h, + int cx, int cy, int cw, int ch); + +extern rfbBool sraClipRect2(int *x, int *y, int *x2, int *y2, + int cx, int cy, int cx2, int cy2); + +#endif diff --git a/rfb/threading.h b/rfb/threading.h new file mode 100644 index 0000000..2a49781 --- /dev/null +++ b/rfb/threading.h @@ -0,0 +1,95 @@ +/* + * LibVNCServer/LibVNCClient common platform threading defines and includes. + * + * Copyright (C) 2020 Christian Beier + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifndef _RFB_COMMON_THREADING_H +#define _RFB_COMMON_THREADING_H + +#include + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD +#include +#if 0 /* debugging */ +#define LOCK(mutex) (rfbLog("%s:%d LOCK(%s,0x%x)\n",__FILE__,__LINE__,#mutex,&(mutex)), pthread_mutex_lock(&(mutex))) +#define UNLOCK(mutex) (rfbLog("%s:%d UNLOCK(%s,0x%x)\n",__FILE__,__LINE__,#mutex,&(mutex)), pthread_mutex_unlock(&(mutex))) +#define MUTEX(mutex) pthread_mutex_t (mutex) +#define INIT_MUTEX(mutex) (rfbLog("%s:%d INIT_MUTEX(%s,0x%x)\n",__FILE__,__LINE__,#mutex,&(mutex)), pthread_mutex_init(&(mutex),NULL)) +#define TINI_MUTEX(mutex) (rfbLog("%s:%d TINI_MUTEX(%s)\n",__FILE__,__LINE__,#mutex), pthread_mutex_destroy(&(mutex))) +#define TSIGNAL(cond) (rfbLog("%s:%d TSIGNAL(%s)\n",__FILE__,__LINE__,#cond), pthread_cond_signal(&(cond))) +#define WAIT(cond,mutex) (rfbLog("%s:%d WAIT(%s,%s)\n",__FILE__,__LINE__,#cond,#mutex), pthread_cond_wait(&(cond),&(mutex))) +#define COND(cond) pthread_cond_t (cond) +#define INIT_COND(cond) (rfbLog("%s:%d INIT_COND(%s)\n",__FILE__,__LINE__,#cond), pthread_cond_init(&(cond),NULL)) +#define TINI_COND(cond) (rfbLog("%s:%d TINI_COND(%s)\n",__FILE__,__LINE__,#cond), pthread_cond_destroy(&(cond))) +#define IF_PTHREADS(x) x +#else +#if !NONETWORK +#define LOCK(mutex) pthread_mutex_lock(&(mutex)) +#define UNLOCK(mutex) pthread_mutex_unlock(&(mutex)) +#endif +#define MUTEX(mutex) pthread_mutex_t (mutex) +#define MUTEX_SIZE (sizeof(pthread_mutex_t)) +#define INIT_MUTEX(mutex) pthread_mutex_init(&(mutex),NULL) +#define TINI_MUTEX(mutex) pthread_mutex_destroy(&(mutex)) +#define TSIGNAL(cond) pthread_cond_signal(&(cond)) +#define WAIT(cond,mutex) pthread_cond_wait(&(cond),&(mutex)) +#define COND(cond) pthread_cond_t (cond) +#define INIT_COND(cond) pthread_cond_init(&(cond),NULL) +#define TINI_COND(cond) pthread_cond_destroy(&(cond)) +#define IF_PTHREADS(x) x +#define THREAD_ROUTINE_RETURN_TYPE void* +#define THREAD_ROUTINE_RETURN_VALUE NULL +#define THREAD_SLEEP_MS(ms) usleep(ms*1000) +#define THREAD_JOIN(thread) pthread_join(thread, NULL) +#define CURRENT_THREAD_ID pthread_self() +#endif +#elif defined(LIBVNCSERVER_HAVE_WIN32THREADS) +#include +#define LOCK(mutex) EnterCriticalSection(&(mutex)) +#define UNLOCK(mutex) LeaveCriticalSection(&(mutex)) +#define MUTEX(mutex) CRITICAL_SECTION (mutex) +#define MUTEX_SIZE (sizeof(CRITICAL_SECTION)) +#define INIT_MUTEX(mutex) InitializeCriticalSection(&(mutex)) +#define TINI_MUTEX(mutex) DeleteCriticalSection(&(mutex)) +#define TSIGNAL(cond) WakeAllConditionVariable(&(cond)) +#define WAIT(cond,mutex) SleepConditionVariableCS(&(cond),&(mutex),INFINITE); +#define COND(cond) CONDITION_VARIABLE (cond) +#define INIT_COND(cond) InitializeConditionVariable(&(cond)); +#define TINI_COND(cond) +#define IF_PTHREADS(x) +#define THREAD_ROUTINE_RETURN_TYPE void +#define THREAD_ROUTINE_RETURN_VALUE +#define THREAD_SLEEP_MS(ms) Sleep(ms) +#define THREAD_JOIN(thread) WaitForSingleObject((HANDLE)thread, INFINITE) +#define CURRENT_THREAD_ID GetCurrentThreadId() +#else +#define LOCK(mutex) +#define UNLOCK(mutex) +#define MUTEX(mutex) +#define INIT_MUTEX(mutex) +#define TINI_MUTEX(mutex) +#define TSIGNAL(cond) +#define WAIT(cond,mutex) this_is_unsupported +#define COND(cond) +#define INIT_COND(cond) +#define TINI_COND(cond) +#define IF_PTHREADS(x) +#endif + +#endif /* _RFB_COMMON_THREADING_H */ diff --git a/vncserver.c b/vncserver.c index d586310..e876800 100644 --- a/vncserver.c +++ b/vncserver.c @@ -21,6 +21,9 @@ * DEALINGS IN THE SOFTWARE. */ +#define LCD_WIDTH 1024 +#define LCD_HEIGHT 768 + #include "config.h" #include @@ -45,6 +48,9 @@ #include #include +#include +#include + #include #include "weston-screenshooter-client-protocol.h" #include "shared/os-compatibility.h" @@ -58,6 +64,12 @@ * the compositor and serves as a test bed for implementing client * side marshalling outside libwayland.so */ +// VNC +const char *passwords[2] = {"1234", 0}; +char *fb = NULL; +rfbScreenInfoPtr server; + +// weston_clone_app int isloop = 1; struct image *pimage; @@ -992,6 +1004,74 @@ char *get_weston_screen_image() return cap_img; } +/************************************************************************************************/ +/* vnc callback */ +// https://github.com/LibVNC/libvncserver/blob/master/examples/example.c + +static void doptr(int buttonMask, int x, int y, rfbClientPtr cl) +{ + printf("buttonMask[%x] x[%d] y[%d]\n",buttonMask, x, y); +} + +static void dokey(rfbBool down, rfbKeySym key, rfbClientPtr cl) +{ + printf("%s[%x] key[%x:%d:%c]\n",down?"down":"up",down, key, key, key & 0x7F); +} + +typedef struct ClientData { + rfbBool oldButton; + int oldx,oldy; +} ClientData; + +static void clientgone(rfbClientPtr cl) +{ + free(cl->clientData); + cl->clientData = NULL; +} + +static enum rfbNewClientAction newclient(rfbClientPtr cl) +{ + cl->clientData = (void*)calloc(sizeof(ClientData),1); + cl->clientGoneHook = clientgone; + return RFB_CLIENT_ACCEPT; +} + +int init_vnc(int argc, char **argv) +{ + int WIDTH = LCD_WIDTH; + int HEIGHT = LCD_HEIGHT; + int BPS = 8; + int SPP = 3; + int BPP = 4; + + server = rfbGetScreen(&argc, argv, WIDTH, HEIGHT, BPS, SPP, BPP); + if (!server) { + printf("Get Screen failed"); + return -1; + } + + + server->frameBuffer = fb = (char *)malloc(WIDTH * HEIGHT * BPP); + if (!server->frameBuffer) { + printf("Memory allocation failed"); + return -1; + } + + server->authPasswdData = (void *)passwords; + server->passwordCheck = rfbCheckPasswordByList; + + server->ptrAddEvent = doptr; + server->kbdAddEvent = dokey; + + server->newClientHook = newclient; + server->httpDir = "./htdocs"; + server->httpEnableProxyConnect = TRUE; + + rfbInitServer(server); + rfbRunEventLoop(server, -1, TRUE); +} + +/************************************************************************************************/ int main(int argc, char *argv[]) { struct display *d; // image.c variable @@ -999,6 +1079,7 @@ int main(int argc, char *argv[]) int image_counter = 0; char *cap_img = NULL; struct timespec start_time, end_time; + init_vnc(argc, argv); d = display_create(&argc, argv); cap_img = get_weston_screen_image(); @@ -1057,5 +1138,8 @@ int main(int argc, char *argv[]) display_destroy(d); + free(fb); + rfbScreenCleanup(server); + return 0; } diff --git a/weston-vncserver b/weston-vncserver index 7a67ce428ff35bb3cb8fc8e52a3bdd6977be8f7a..59299ea313eaefe654c1287a8d55af5e6df81a56 100755 GIT binary patch literal 165920 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.sw-v%whDf3V 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�}l=&UnII_#Z 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 z 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 CpI%G= -- 2.1.4