diff --git a/libguac/Makefile.am b/libguac/Makefile.am index 25bb04b2..3c69a92d 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -48,7 +48,7 @@ libguac_la_SOURCES = src/client.c src/socket.c src/protocol.c src/client-handler libguac_la_LDFLAGS = -version-info 3:1:0 -noinst_HEADERS = include/palette.h include/client-handlers.h +noinst_HEADERS = include/palette.h include/client-handlers.h include/unicode.h EXTRA_DIST = LICENSE doc/Doxyfile diff --git a/libguac/include/unicode.h b/libguac/include/unicode.h new file mode 100644 index 00000000..d9abd849 --- /dev/null +++ b/libguac/include/unicode.h @@ -0,0 +1,60 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _GUAC_UNICODE_H +#define _GUAC_UNICODE_H + +/** + * Given the initial byte of a single UTF-8 character, returns the overall + * byte size of the entire character. + * + * @param c The initial byte of the character to check. + * @return The number of bytes in the given character overall. + */ +size_t guac_utf8_charsize(unsigned char c); + +/** + * Given a UTF-8-encoded string, returns the length of the string in characters + * (not bytes). + * + * @param str The UTF-8 string to calculate the length of. + * @return The length in characters of the given UTF-8 string. + */ +size_t guac_utf8_strlen(const char* str); + +#endif + diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 85c4e422..0ace2ac6 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -70,49 +70,14 @@ #include "protocol.h" #include "error.h" #include "palette.h" +#include "unicode.h" /* Output formatting functions */ -ssize_t __guac_utf8_strlen(const char* str) { - - /* The current length of the string */ - int length = 0; - - /* Number of characters before start of next character */ - int skip = 0; - - while (*str != 0) { - - /* If skipping, then skip */ - if (skip > 0) skip--; - - /* Otherwise, determine next skip value, and increment length */ - else { - - /* Get next character */ - unsigned char c = (unsigned char) *str; - - /* Determine skip value (size in bytes of rest of character) */ - if ((c >>= 1) == 0x7E) skip = 5; - else if ((c >>= 1) == 0x3E) skip = 4; - else if ((c >>= 1) == 0x1E) skip = 3; - else if ((c >>= 1) == 0x0E) skip = 2; - else if ((c >>= 1) == 0x06) skip = 1; - - length++; - } - - str++; - } - - return length; - -} - ssize_t __guac_socket_write_length_string(guac_socket* socket, const char* str) { return - guac_socket_write_int(socket, __guac_utf8_strlen(str)) + guac_socket_write_int(socket, guac_utf8_strlen(str)) || guac_socket_write_string(socket, ".") || guac_socket_write_string(socket, str); diff --git a/libguac/src/unicode.c b/libguac/src/unicode.c new file mode 100644 index 00000000..de80c8ed --- /dev/null +++ b/libguac/src/unicode.c @@ -0,0 +1,85 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "unicode.h" + +size_t guac_utf8_charsize(unsigned char c) { + + /* Determine size in bytes of character */ + if ((c >>= 1) == 0x7E) return 6; + if ((c >>= 1) == 0x3E) return 5; + if ((c >>= 1) == 0x1E) return 4; + if ((c >>= 1) == 0x0E) return 3; + if ((c >>= 1) == 0x06) return 2; + + /* Default to one character */ + return 1; + +} + +size_t guac_utf8_strlen(const char* str) { + + /* The current length of the string */ + int length = 0; + + /* Number of characters before start of next character */ + int skip = 0; + + while (*str != 0) { + + /* If skipping, then skip */ + if (skip > 0) skip--; + + /* Otherwise, determine next skip value, and increment length */ + else { + + /* Get next character */ + unsigned char c = (unsigned char) *str; + + /* Determine skip value (size in bytes of rest of character) */ + skip = guac_utf8_charsize(c) - 1; + + length++; + } + + str++; + } + + return length; + +} +