00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include <errno.h>
00026 #include <stdio.h>
00027 #include <signal.h>
00028 #include <string.h>
00029
00030 #include "gnc-glib-utils.h"
00031
00032 #ifdef G_OS_WIN32
00033 #include <windows.h>
00034 #endif
00035
00036 int
00037 safe_utf8_collate (const char * da, const char * db)
00038 {
00039 if (da && !(*da))
00040 da = NULL;
00041 if (db && !(*db))
00042 db = NULL;
00043
00044 if (da && db)
00045 return g_utf8_collate(da, db);
00046 if (da)
00047 return 1;
00048 if (db)
00049 return -1;
00050 return 0;
00051 }
00052
00053
00054
00055
00056
00057
00058
00059
00060 #define UTF8_COMPUTE(Char, Mask, Len) \
00061 if (Char < 128) \
00062 { \
00063 Len = 1; \
00064 Mask = 0x7f; \
00065 } \
00066 else if ((Char & 0xe0) == 0xc0) \
00067 { \
00068 Len = 2; \
00069 Mask = 0x1f; \
00070 } \
00071 else if ((Char & 0xf0) == 0xe0) \
00072 { \
00073 Len = 3; \
00074 Mask = 0x0f; \
00075 } \
00076 else if ((Char & 0xf8) == 0xf0) \
00077 { \
00078 Len = 4; \
00079 Mask = 0x07; \
00080 } \
00081 else if ((Char & 0xfc) == 0xf8) \
00082 { \
00083 Len = 5; \
00084 Mask = 0x03; \
00085 } \
00086 else if ((Char & 0xfe) == 0xfc) \
00087 { \
00088 Len = 6; \
00089 Mask = 0x01; \
00090 } \
00091 else \
00092 Len = -1;
00093
00094 #define UTF8_LENGTH(Char) \
00095 ((Char) < 0x80 ? 1 : \
00096 ((Char) < 0x800 ? 2 : \
00097 ((Char) < 0x10000 ? 3 : \
00098 ((Char) < 0x200000 ? 4 : \
00099 ((Char) < 0x4000000 ? 5 : 6)))))
00100
00101
00102 #define UTF8_GET(Result, Chars, Count, Mask, Len) \
00103 (Result) = (Chars)[0] & (Mask); \
00104 for ((Count) = 1; (Count) < (Len); ++(Count)) \
00105 { \
00106 if (((Chars)[(Count)] & 0xc0) != 0x80) \
00107 { \
00108 (Result) = -1; \
00109 break; \
00110 } \
00111 (Result) <<= 6; \
00112 (Result) |= ((Chars)[(Count)] & 0x3f); \
00113 }
00114
00115 #define UNICODE_VALID(Char) \
00116 ((Char) < 0x110000 && \
00117 (((Char) & 0xFFFFF800) != 0xD800) && \
00118 ((Char) < 0xFDD0 || (Char) > 0xFDEF) && \
00119 ((Char) >= 0x20 || (Char) == 0x09 || (Char) == 0x0A || (Char) == 0x0D) && \
00120 ((Char) & 0xFFFE) != 0xFFFE)
00121
00122 gboolean
00123 gnc_utf8_validate(const gchar *str,
00124 gssize max_len,
00125 const gchar **end)
00126 {
00127
00128 const gchar *p;
00129
00130 g_return_val_if_fail (str != NULL, FALSE);
00131
00132 if (end)
00133 *end = str;
00134
00135 p = str;
00136
00137 while ((max_len < 0 || (p - str) < max_len) && *p)
00138 {
00139 int i, mask = 0, len;
00140 gunichar result;
00141 unsigned char c = (unsigned char) *p;
00142
00143 UTF8_COMPUTE (c, mask, len);
00144
00145 if (len == -1)
00146 break;
00147
00148
00149 if (max_len >= 0 &&
00150 ((max_len - (p - str)) < len))
00151 break;
00152
00153 UTF8_GET (result, p, i, mask, len);
00154
00155 if (UTF8_LENGTH (result) != len)
00156 break;
00157
00158 if (result == (gunichar)-1)
00159 break;
00160
00161 if (!UNICODE_VALID (result))
00162 break;
00163
00164 p += len;
00165 }
00166
00167 if (end)
00168 *end = p;
00169
00170
00171
00172
00173 if (max_len >= 0 &&
00174 p != (str + max_len))
00175 return FALSE;
00176 else if (max_len < 0 &&
00177 *p != '\0')
00178 return FALSE;
00179 else
00180 return TRUE;
00181 }
00182
00183 void
00184 gnc_utf8_strip_invalid (gchar *str)
00185 {
00186 gchar *end;
00187 gint len;
00188
00189 g_return_if_fail(str);
00190
00191 if (gnc_utf8_validate(str, -1, (const gchar **)&end))
00192 return;
00193
00194 g_warning("Invalid utf8 string: %s", str);
00195 do {
00196 len = strlen(end);
00197 memmove(end, end+1, len);
00198 } while (!gnc_utf8_validate(str, -1, (const gchar **)&end));
00199 }
00200
00201 gchar *
00202 gnc_utf8_strip_invalid_strdup(const gchar* str)
00203 {
00204 gchar *result = g_strdup (str);
00205 gnc_utf8_strip_invalid (result);
00206 return result;
00207 }
00208
00209 gchar *
00210 gnc_locale_from_utf8(const gchar* str)
00211 {
00212 gchar * locale_str;
00213 gsize bytes_written = 0;
00214 GError * err = NULL;
00215
00216
00217 locale_str = g_locale_from_utf8(str, -1, NULL, &bytes_written, &err);
00218 if (err) {
00219 g_warning("g_locale_from_utf8 failed: %s", err->message);
00220 g_error_free(err);
00221 }
00222
00223 return locale_str;
00224 }
00225
00226 gchar *
00227 gnc_locale_to_utf8(const gchar* str)
00228 {
00229 gchar * utf8_str;
00230 gsize bytes_written = 0;
00231 GError * err = NULL;
00232
00233
00234 utf8_str = g_locale_to_utf8(str, -1, NULL, &bytes_written, &err);
00235 if (err) {
00236 g_warning("g_locale_to_utf8 failed: %s", err->message);
00237 g_error_free(err);
00238 }
00239
00240 return utf8_str;
00241 }
00242
00243 GList*
00244 gnc_g_list_map(GList* list, GncGMapFunc fn, gpointer user_data)
00245 {
00246 GList *rtn = NULL;
00247 for (; list != NULL; list = list->next)
00248 {
00249 rtn = g_list_append(rtn, (*fn)(list->data, user_data));
00250 }
00251 return rtn;
00252 }
00253
00254 void
00255 gnc_g_list_cut(GList **list, GList *cut_point)
00256 {
00257 if (list == NULL || *list == NULL)
00258 return;
00259
00260
00261 if (cut_point->prev == NULL)
00262 {
00263 *list = NULL;
00264 return;
00265 }
00266
00267 cut_point->prev->next = NULL;
00268 cut_point->prev = NULL;
00269 }
00270
00271 void
00272 gnc_scm_log_warn(const gchar *msg)
00273 {
00274 g_log("gnc.scm", G_LOG_LEVEL_WARNING, "%s", msg);
00275 }
00276
00277 void
00278 gnc_scm_log_error(const gchar *msg)
00279 {
00280 g_log("gnc.scm", G_LOG_LEVEL_CRITICAL, "%s", msg);
00281 }
00282
00283 void
00284 gnc_scm_log_msg(const gchar *msg)
00285 {
00286 g_log("gnc.scm", G_LOG_LEVEL_MESSAGE, "%s", msg);
00287 }
00288
00289 void
00290 gnc_scm_log_debug(const gchar *msg)
00291 {
00292 g_log("gnc.scm", G_LOG_LEVEL_DEBUG, "%s", msg);
00293 }
00294
00295 void gnc_gpid_kill(GPid pid)
00296 {
00297 #ifdef G_OS_WIN32
00298 if (!TerminateProcess((HANDLE) pid, 0)) {
00299 gchar *msg = g_win32_error_message(GetLastError());
00300 g_warning("Could not kill child process: %s", msg ? msg : "(null)");
00301 g_free(msg);
00302 }
00303 #else
00304 if (kill(pid, SIGKILL)) {
00305 g_warning("Could not kill child process: %s", g_strerror(errno));
00306 }
00307 #endif
00308 }