diff --git a/apps/epics/main.c b/apps/epics/main.c index 273a6943..06a0699d 100644 --- a/apps/epics/main.c +++ b/apps/epics/main.c @@ -31,6 +31,9 @@ #include #include #include /* for time */ +#ifdef __STDC_ISO_10646__ +#include +#endif #include #include #include "bacnet/config.h" @@ -1438,6 +1441,17 @@ int main(int argc, char *argv[]) address_init(); Init_Service_Handlers(); dlenv_init(); +#ifdef __STDC_ISO_10646__ + /* Internationalized programs must call setlocale() + * to initiate a specific language operation. + * This can be done by calling setlocale() as follows. + * If your native locale doesn't use UTF-8 encoding + * you need to replace the empty string with a + * locale like "en_US.utf8" which is the same as the string + * used in the enviromental variable "LANG=en_US.UTF-8". + */ + setlocale(LC_ALL, ""); +#endif atexit(datalink_cleanup); /* configure the timeout values */ diff --git a/apps/readprop/main.c b/apps/readprop/main.c index c4d772f3..e95b1886 100644 --- a/apps/readprop/main.c +++ b/apps/readprop/main.c @@ -29,6 +29,9 @@ #include #include #include /* for time */ +#ifdef __STDC_ISO_10646__ +#include +#endif #define PRINT_ENABLED 1 @@ -363,6 +366,17 @@ int main(int argc, char *argv[]) Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE); Init_Service_Handlers(); dlenv_init(); +#ifdef __STDC_ISO_10646__ + /* Internationalized programs must call setlocale() + * to initiate a specific language operation. + * This can be done by calling setlocale() as follows. + * If your native locale doesn't use UTF-8 encoding + * you need to replace the empty string with a + * locale like "en_US.utf8" which is the same as the string + * used in the enviromental variable "LANG=en_US.UTF-8". + */ + setlocale(LC_ALL, ""); +#endif atexit(datalink_cleanup); /* configure the timeout values */ last_seconds = time(NULL); diff --git a/apps/readpropm/main.c b/apps/readpropm/main.c index 7a92980a..4580c635 100644 --- a/apps/readpropm/main.c +++ b/apps/readpropm/main.c @@ -29,6 +29,9 @@ #include #include #include /* for time */ +#ifdef __STDC_ISO_10646__ +#include +#endif #define PRINT_ENABLED 1 @@ -423,6 +426,17 @@ int main(int argc, char *argv[]) address_init(); Init_Service_Handlers(); dlenv_init(); +#ifdef __STDC_ISO_10646__ + /* Internationalized programs must call setlocale() + * to initiate a specific language operation. + * This can be done by calling setlocale() as follows. + * If your native locale doesn't use UTF-8 encoding + * you need to replace the empty string with a + * locale like "en_US.utf8" which is the same as the string + * used in the enviromental variable "LANG=en_US.UTF-8". + */ + setlocale(LC_ALL, ""); +#endif atexit(datalink_cleanup); /* configure the timeout values */ last_seconds = time(NULL); diff --git a/apps/readrange/main.c b/apps/readrange/main.c index b53ec1fd..f7c63c5e 100644 --- a/apps/readrange/main.c +++ b/apps/readrange/main.c @@ -31,6 +31,9 @@ #include #include #include /* for time */ +#ifdef __STDC_ISO_10646__ +#include +#endif #include "bacnet/bacdef.h" #include "bacnet/config.h" #include "bacnet/bactext.h" @@ -320,6 +323,17 @@ int main(int argc, char *argv[]) address_init(); Init_Service_Handlers(); dlenv_init(); +#ifdef __STDC_ISO_10646__ + /* Internationalized programs must call setlocale() + * to initiate a specific language operation. + * This can be done by calling setlocale() as follows. + * If your native locale doesn't use UTF-8 encoding + * you need to replace the empty string with a + * locale like "en_US.utf8" which is the same as the string + * used in the enviromental variable "LANG=en_US.UTF-8". + */ + setlocale(LC_ALL, ""); +#endif atexit(datalink_cleanup); /* configure the timeout values */ last_seconds = time(NULL); diff --git a/src/bacnet/bacapp.c b/src/bacnet/bacapp.c index d9bb8238..6a0cfe08 100644 --- a/src/bacnet/bacapp.c +++ b/src/bacnet/bacapp.c @@ -35,8 +35,12 @@ #include #include #include -#include -#include +#include /* for strtol */ +#include /* for isalnum */ +#ifdef __STDC_ISO_10646__ +#include +#include +#endif #include "bacnet/bacenum.h" #include "bacnet/bacdcode.h" #include "bacnet/bacint.h" @@ -1038,6 +1042,12 @@ int bacapp_snprintf_value( char *p_str = str; size_t rem_str_len = str_len; char temp_str[32]; +#ifdef __STDC_ISO_10646__ + /* Wide character (decoded from multi-byte character). */ + wchar_t wc; + /* Wide character length in bytes. */ + int wclen; +#endif if (object_value && object_value->value) { value = object_value->value; @@ -1102,17 +1112,50 @@ int bacapp_snprintf_value( char_str = characterstring_value(&value->type.Character_String); if (!append_str(&p_str, &rem_str_len, "\"")) { break; -} - for (i = 0; i < len; i++) { - if (isprint(*((unsigned char *)char_str))) { - snprintf(temp_str, sizeof(temp_str), "%c", *char_str); - } else { - snprintf(temp_str, sizeof(temp_str), "%c", '.'); + } + #ifdef __STDC_ISO_10646__ + if (characterstring_encoding(&value->type.Character_String) == + CHARACTER_UTF8) { + while (len > 0) { + wclen = mbtowc(&wc, char_str, MB_CUR_MAX); + if (wclen == -1) { + /* Encoding error, reset state: */ + mbtowc(NULL, NULL, MB_CUR_MAX); + /* After handling an invalid byte, + retry with the next one. */ + wclen = 1; + wc = L'?'; + } else { + if (!iswprint(wc)) { + wc = L'.'; + } + } + snprintf(temp_str, sizeof(temp_str), "%lc", wc); + if (!append_str(&p_str, &rem_str_len, temp_str)) { + break; + } + if (len > wclen) { + len -= wclen; + char_str += wclen; + } else { + len = 0; + } + } + } else + #endif + { + for (i = 0; i < len; i++) { + if (isprint(*((unsigned char *)char_str))) { + snprintf(temp_str, sizeof(temp_str), "%c", + *char_str); + } else { + snprintf(temp_str, sizeof(temp_str), "%c", '.'); + } + if (!append_str(&p_str, &rem_str_len, temp_str)) { + break; + } + char_str++; } - if (!append_str(&p_str, &rem_str_len, temp_str)) { - break; -} - char_str++; } if ((i == len) && append_str(&p_str, &rem_str_len, "\"")) { /* Everything is fine. Indicate how many bytes were */