CMultibyte.cpp

00001 /*
00002  * synergy -- mouse and keyboard sharing utility
00003  * Copyright (C) 2002 Chris Schoeneman
00004  * 
00005  * This package is free software you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * found in the file COPYING that should have accompanied this file.
00008  * 
00009  * This package is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  */
00014 
00015 #ifndef CMULTIBYTE_H
00016 #define CMULTIBYTE_H
00017 
00018 #include "common.h"
00019 #include "CArch.h"
00020 #include <climits>
00021 #include <cstring>
00022 #include <cstdlib>
00023 #if HAVE_LOCALE_H
00024 #   include <locale.h>
00025 #endif
00026 #if HAVE_WCHAR_H || defined(_MSC_VER)
00027 #   include <wchar.h>
00028 #elif __APPLE__
00029     // wtf?  Darwin puts mbtowc() et al. in stdlib
00030 #   include <cstdlib>
00031 #else
00032     // platform apparently has no wchar_t support.  provide dummy
00033     // implementations.  hopefully at least the C++ compiler has
00034     // a built-in wchar_t type.
00035 
00036 static inline
00037 int
00038 mbtowc(wchar_t* dst, const char* src, int n)
00039 {
00040     *dst = static_cast<wchar_t>(*src);
00041     return 1;
00042 }
00043 
00044 static inline
00045 int
00046 wctomb(char* dst, wchar_t src)
00047 {
00048     *dst = static_cast<char>(src);
00049     return 1;
00050 }
00051 
00052 #endif
00053 
00054 //
00055 // use C library non-reentrant multibyte conversion with mutex
00056 //
00057 
00058 static CArchMutex       s_mutex = NULL;
00059 
00060 ARCH_STRING::ARCH_STRING()
00061 {
00062     s_mutex = ARCH->newMutex();
00063 
00064 #if HAVE_LOCALE_H
00065     // see if we can convert a Latin-1 character
00066     char mb[MB_LEN_MAX];
00067     if (wctomb(mb, 0xe3) == -1) {
00068         // can't convert.  try another locale so we can convert latin-1.
00069         setlocale(LC_CTYPE, "en_US");
00070     }
00071 #endif
00072 }
00073 
00074 ARCH_STRING::~ARCH_STRING()
00075 {
00076     ARCH->closeMutex(s_mutex);
00077     s_mutex = NULL;
00078 }
00079 
00080 int
00081 ARCH_STRING::convStringWCToMB(char* dst,
00082                 const wchar_t* src, UInt32 n, bool* errors)
00083 {
00084     int len = 0;
00085 
00086     bool dummyErrors;
00087     if (errors == NULL) {
00088         errors = &dummyErrors;
00089     }
00090 
00091     ARCH->lockMutex(s_mutex);
00092     if (dst == NULL) {
00093         char dummy[MB_LEN_MAX];
00094         for (const wchar_t* scan = src; n > 0; ++scan, --n) {
00095             int mblen = wctomb(dummy, *scan);
00096             if (mblen == -1) {
00097                 *errors = true;
00098                 mblen   = 1;
00099             }
00100             len += mblen;
00101         }
00102         int mblen = wctomb(dummy, L'\0');
00103         if (mblen != -1) {
00104             len += mblen - 1;
00105         }
00106     }
00107     else {
00108         char* dst0 = dst;
00109         for (const wchar_t* scan = src; n > 0; ++scan, --n) {
00110             int mblen = wctomb(dst, *scan);
00111             if (mblen == -1) {
00112                 *errors = true;
00113                 *dst++  = '?';
00114             }
00115             else {
00116                 dst    += mblen;
00117             }
00118         }
00119         int mblen = wctomb(dst, L'\0');
00120         if (mblen != -1) {
00121             // don't include nul terminator
00122             dst += mblen - 1;
00123         }
00124         len = (int)(dst - dst0);
00125     }
00126     ARCH->unlockMutex(s_mutex);
00127 
00128     return len;
00129 }
00130 
00131 int
00132 ARCH_STRING::convStringMBToWC(wchar_t* dst,
00133                 const char* src, UInt32 n, bool* errors)
00134 {
00135     int len = 0;
00136     wchar_t dummy;
00137 
00138     bool dummyErrors;
00139     if (errors == NULL) {
00140         errors = &dummyErrors;
00141     }
00142 
00143     ARCH->lockMutex(s_mutex);
00144     if (dst == NULL) {
00145         for (const char* scan = src; n > 0; ) {
00146             int mblen = mbtowc(&dummy, scan, n);
00147             switch (mblen) {
00148             case -2:
00149                 // incomplete last character.  convert to unknown character.
00150                 *errors = true;
00151                 len    += 1;
00152                 n       = 0;
00153                 break;
00154 
00155             case -1:
00156                 // invalid character.  count one unknown character and
00157                 // start at the next byte.
00158                 *errors = true;
00159                 len    += 1;
00160                 scan   += 1;
00161                 n      -= 1;
00162                 break;
00163 
00164             case 0:
00165                 len    += 1;
00166                 scan   += 1;
00167                 n      -= 1;
00168                 break;
00169 
00170             default:
00171                 // normal character
00172                 len    += 1;
00173                 scan   += mblen;
00174                 n      -= mblen;
00175                 break;
00176             }
00177         }
00178     }
00179     else {
00180         wchar_t* dst0 = dst;
00181         for (const char* scan = src; n > 0; ++dst) {
00182             int mblen = mbtowc(dst, scan, n);
00183             switch (mblen) {
00184             case -2:
00185                 // incomplete character.  convert to unknown character.
00186                 *errors = true;
00187                 *dst    = (wchar_t)0xfffd;
00188                 n       = 0;
00189                 break;
00190 
00191             case -1:
00192                 // invalid character.  count one unknown character and
00193                 // start at the next byte.
00194                 *errors = true;
00195                 *dst    = (wchar_t)0xfffd;
00196                 scan   += 1;
00197                 n      -= 1;
00198                 break;
00199 
00200             case 0:
00201                 *dst    = (wchar_t)0x0000;
00202                 scan   += 1;
00203                 n      -= 1;
00204                 break;
00205 
00206             default:
00207                 // normal character
00208                 scan   += mblen;
00209                 n      -= mblen;
00210                 break;
00211             }
00212         }
00213         len = (int)(dst - dst0);
00214     }
00215     ARCH->unlockMutex(s_mutex);
00216 
00217     return len;
00218 }
00219 
00220 #endif

Generated on Fri Nov 6 00:18:45 2009 for synergy-plus by  doxygen 1.4.7