From c818fb021632cbb68229ba265f01b060e6b6d0f4 Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Fri, 3 Feb 2012 20:21:17 +0000 Subject: Split off UTF-8 code into separate file and add extra functions. Subversion-branch: /trunk/chocolate-doom Subversion-revision: 2489 --- textscreen/Makefile.am | 1 + textscreen/txt_gui.c | 57 +----------------- textscreen/txt_gui.h | 1 + textscreen/txt_utf8.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++++ textscreen/txt_utf8.h | 31 ++++++++++ 5 files changed, 196 insertions(+), 54 deletions(-) create mode 100644 textscreen/txt_utf8.c create mode 100644 textscreen/txt_utf8.h diff --git a/textscreen/Makefile.am b/textscreen/Makefile.am index d6863ca9..fd671645 100644 --- a/textscreen/Makefile.am +++ b/textscreen/Makefile.am @@ -30,6 +30,7 @@ libtextscreen_a_SOURCES = \ txt_smallfont.h \ txt_strut.c txt_strut.h \ txt_table.c txt_table.h \ + txt_utf8.c txt_utf8.h \ txt_widget.c txt_widget.h \ txt_window.c txt_window.h \ txt_window_action.c txt_window_action.h \ diff --git a/textscreen/txt_gui.c b/textscreen/txt_gui.c index 1bcc2e9e..bc869255 100644 --- a/textscreen/txt_gui.c +++ b/textscreen/txt_gui.c @@ -25,6 +25,7 @@ #include "txt_gui.h" #include "txt_io.h" #include "txt_main.h" +#include "txt_utf8.h" typedef struct txt_cliparea_s txt_cliparea_t; @@ -296,58 +297,6 @@ void TXT_DrawString(const char *s) TXT_GotoXY(x + strlen(s), y); } -// Decode UTF-8 character, incrementing *ptr over the decoded bytes. - -static unsigned int DecodeUTF8(const char **ptr) -{ - const char *p = *ptr; - unsigned int c; - - // UTF-8 decode. - - if ((*p & 0x80) == 0) // 1 character (ASCII): - { - c = *p; - *ptr += 1; - } - else if ((p[0] & 0xe0) == 0xc0 // 2 character: - && (p[1] & 0xc0) == 0x80) - { - c = ((p[0] & 0x1f) << 6) - | (p[1] & 0x3f); - *ptr += 2; - } - else if ((p[0] & 0xf0) == 0xe0 // 3 character: - && (p[1] & 0xc0) == 0x80 - && (p[2] & 0xc0) == 0x80) - { - c = ((p[0] & 0x0f) << 12) - | ((p[1] & 0x3f) << 6) - | (p[2] & 0x3f); - *ptr += 3; - } - else if ((p[0] & 0xf8) == 0xf0 // 4 character: - && (p[1] & 0xc0) == 0x80 - && (p[2] & 0xc0) == 0x80 - && (p[3] & 0xc0) == 0x80) - { - c = ((p[0] & 0x07) << 18) - | ((p[1] & 0x3f) << 12) - | ((p[2] & 0x3f) << 6) - | (p[3] & 0x3f); - *ptr += 4; - } - else - { - // Decode failure. - // Don't bother with 5/6 byte sequences. - - c = 0; - } - - return c; -} - static void PutUnicodeChar(unsigned int c) { unsigned int i; @@ -389,7 +338,7 @@ void TXT_DrawUTF8String(const char *s) for (p = s; *p != '\0'; ) { - c = DecodeUTF8(&p); + c = TXT_DecodeUTF8(&p); if (c == 0) { @@ -406,7 +355,7 @@ void TXT_DrawUTF8String(const char *s) } } - TXT_GotoXY(x + strlen(s), y); + TXT_GotoXY(x + TXT_UTF8_Strlen(s), y); } void TXT_DrawHorizScrollbar(int x, int y, int w, int cursor, int range) diff --git a/textscreen/txt_gui.h b/textscreen/txt_gui.h index 06fc7a36..3aa6e629 100644 --- a/textscreen/txt_gui.h +++ b/textscreen/txt_gui.h @@ -34,6 +34,7 @@ void TXT_DrawDesktopBackground(const char *title); void TXT_DrawWindowFrame(const char *title, int x, int y, int w, int h); void TXT_DrawSeparator(int x, int y, int w); void TXT_DrawString(const char *s); +void TXT_DrawUTF8String(const char *s); void TXT_DrawHorizScrollbar(int x, int y, int w, int cursor, int range); void TXT_DrawVertScrollbar(int x, int y, int h, int cursor, int range); diff --git a/textscreen/txt_utf8.c b/textscreen/txt_utf8.c new file mode 100644 index 00000000..1306f265 --- /dev/null +++ b/textscreen/txt_utf8.c @@ -0,0 +1,160 @@ +// Emacs style mode select -*- C++ -*- +//----------------------------------------------------------------------------- +// +// Copyright(C) 2012 Simon Howard +// +// This program 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 program 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 program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA. +// + +#include +#include + +#include "txt_utf8.h" + +// Encode a Unicode character as UTF-8, storing it in the buffer 'p' +// and returning the new, incremented position. + +char *TXT_EncodeUTF8(char *p, unsigned int c) +{ + if (c < 0x80) // 1 character (ASCII): + { + p[0] = c; + return p + 1; + } + else if (c < 0x800) // 2 character: + { + p[0] = 0xc0 | (c >> 6); + p[1] = 0x80 | (c & 0x3f); + return p + 2; + } + else if (c < 0x10000) // 3 chacater: + { + p[0] = 0xe0 | (c >> 12); + p[1] = 0x80 | ((c >> 6) & 0x3f); + p[2] = 0x80 | (c & 0x3f); + return p + 3; + } + else if (c < 0x200000) // 4 character: + { + p[0] = 0xf0 | (c >> 18); + p[1] = 0x80 | ((c >> 12) & 0x3f); + p[2] = 0x80 | ((c >> 6) & 0x3f); + p[3] = 0x80 | (c & 0x3f); + return p + 4; + } + else + { + // Too big! + + return p; + } +} + +// Decode UTF-8 character, incrementing *ptr over the decoded bytes. + +unsigned int TXT_DecodeUTF8(const char **ptr) +{ + const char *p = *ptr; + unsigned int c; + + // UTF-8 decode. + + if ((*p & 0x80) == 0) // 1 character (ASCII): + { + c = *p; + *ptr += 1; + } + else if ((p[0] & 0xe0) == 0xc0 // 2 character: + && (p[1] & 0xc0) == 0x80) + { + c = ((p[0] & 0x1f) << 6) + | (p[1] & 0x3f); + *ptr += 2; + } + else if ((p[0] & 0xf0) == 0xe0 // 3 character: + && (p[1] & 0xc0) == 0x80 + && (p[2] & 0xc0) == 0x80) + { + c = ((p[0] & 0x0f) << 12) + | ((p[1] & 0x3f) << 6) + | (p[2] & 0x3f); + *ptr += 3; + } + else if ((p[0] & 0xf8) == 0xf0 // 4 character: + && (p[1] & 0xc0) == 0x80 + && (p[2] & 0xc0) == 0x80 + && (p[3] & 0xc0) == 0x80) + { + c = ((p[0] & 0x07) << 18) + | ((p[1] & 0x3f) << 12) + | ((p[2] & 0x3f) << 6) + | (p[3] & 0x3f); + *ptr += 4; + } + else + { + // Decode failure. + // Don't bother with 5/6 byte sequences. + + c = 0; + } + + return c; +} + +// Count the number of characters in a UTF-8 string. + +unsigned int TXT_UTF8_Strlen(const char *s) +{ + const char *p; + unsigned int result = 0; + unsigned int c; + + for (p = s; *p != '\0';) + { + c = TXT_DecodeUTF8(&p); + + if (c == 0) + { + break; + } + + ++result; + } + + return result; +} + +// Skip past the first n characters in a UTF-8 string. + +char *TXT_UTF8_SkipChars(const char *s, unsigned int n) +{ + unsigned int i; + const char *p; + + p = s; + + for (i = 0; i < n; ++i) + { + if (TXT_DecodeUTF8(&p) == 0) + { + break; + } + } + + return (char *) p; +} + diff --git a/textscreen/txt_utf8.h b/textscreen/txt_utf8.h new file mode 100644 index 00000000..dc519032 --- /dev/null +++ b/textscreen/txt_utf8.h @@ -0,0 +1,31 @@ +// Emacs style mode select -*- C++ -*- +//----------------------------------------------------------------------------- +// +// Copyright(C) 2012 Simon Howard +// +// This program 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 program 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 program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA. +// + +#ifndef TXT_UTF8_H +#define TXT_UTF8_H + +char *TXT_EncodeUTF8(char *p, unsigned int c); +unsigned int TXT_DecodeUTF8(const char **ptr); +unsigned int TXT_UTF8_Strlen(const char *s); +char *TXT_UTF8_SkipChars(const char *s, unsigned int n); + +#endif /* #ifndef TXT_UTF8_H */ + -- cgit v1.2.3