Code

Warning cleanup (including OFFSET_OF warning)
[inkscape.git] / src / io / sys.cpp
2 /*
3  * System abstraction utility routines
4  *
5  * Authors:
6  *   Jon A. Cruz <jon@joncruz.org>
7  *
8  * Copyright (C) 2004-2005 Authors
9  *
10  * Released under GNU GPL, read the file 'COPYING' for more information
11  */
14 #ifdef HAVE_CONFIG_H
15 # include "config.h"
16 #endif
18 #include <glib/gutils.h>
19 #if GLIB_CHECK_VERSION(2,6,0)
20     #include <glib/gstdio.h>
21 #endif
22 #include <glibmm/ustring.h>
23 #include <gtk/gtkmessagedialog.h>
25 #include "prefs-utils.h"
26 #include "sys.h"
28 #ifdef WIN32
30 // For now to get at is_os_wide().
31 #include "extension/internal/win32.h"
32 using Inkscape::Extension::Internal::PrintWin32;
34 #endif
36 //#define INK_DUMP_FILENAME_CONV 1
37 #undef INK_DUMP_FILENAME_CONV
39 //#define INK_DUMP_FOPEN 1
40 #undef INK_DUMP_FOPEN
42 void dump_str(gchar const *str, gchar const *prefix);
43 void dump_ustr(Glib::ustring const &ustr);
45 extern guint update_in_progress;
48 #define DEBUG_MESSAGE(key, ...) \
49 {\
50     gint dump = prefs_get_int_attribute_limited("options.bulia", #key, 0, 0, 1);\
51     gint dumpD = prefs_get_int_attribute_limited("options.bulia", #key"D", 0, 0, 1);\
52     gint dumpD2 = prefs_get_int_attribute_limited("options.bulia", #key"D2", 0, 0, 1);\
53     dumpD &= ( (update_in_progress == 0) || dumpD2 );\
54     if ( dump )\
55     {\
56         g_message( __VA_ARGS__ );\
57 \
58     }\
59     if ( dumpD )\
60     {\
61         GtkWidget *dialog = gtk_message_dialog_new(NULL,\
62                                                    GTK_DIALOG_DESTROY_WITH_PARENT, \
63                                                    GTK_MESSAGE_INFO,    \
64                                                    GTK_BUTTONS_OK,      \
65                                                    __VA_ARGS__          \
66                                                    );\
67         g_signal_connect_swapped(dialog, "response",\
68                                  G_CALLBACK(gtk_widget_destroy),        \
69                                  dialog);                               \
70         gtk_widget_show_all( dialog );\
71     }\
72 }
77 void Inkscape::IO::dump_fopen_call( char const *utf8name, char const *id )
78 {
79 #ifdef INK_DUMP_FOPEN
80     Glib::ustring str;
81     for ( int i = 0; utf8name[i]; i++ )
82     {
83         if ( utf8name[i] == '\\' )
84         {
85             str += "\\\\";
86         }
87         else if ( (utf8name[i] >= 0x20) && ((0x0ff & utf8name[i]) <= 0x7f) )
88         {
89             str += utf8name[i];
90         }
91         else
92         {
93             gchar tmp[32];
94             g_snprintf( tmp, sizeof(tmp), "\\x%02x", (0x0ff & utf8name[i]) );
95             str += tmp;
96         }
97     }
98     g_message( "fopen call %s for [%s]", id, str.data() );
99 #else
100     (void)utf8name;
101     (void)id;
102 #endif
105 FILE *Inkscape::IO::fopen_utf8name( char const *utf8name, char const *mode )
107     static gint counter = 0;
108     FILE* fp = NULL;
110     DEBUG_MESSAGE( dumpOne, "entering fopen_utf8name( '%s', '%s' )[%d]", utf8name, mode, (counter++) );
112 #ifndef WIN32
113     DEBUG_MESSAGE( dumpOne, "           STEP 0              ( '%s', '%s' )[%d]", utf8name, mode, (counter++) );
114     gchar *filename = g_filename_from_utf8( utf8name, -1, NULL, NULL, NULL );
115     if ( filename )
116     {
117         DEBUG_MESSAGE( dumpOne, "           STEP 1              ( '%s', '%s' )[%d]", utf8name, mode, (counter++) );
118         fp = std::fopen(filename, mode);
119         DEBUG_MESSAGE( dumpOne, "           STEP 2              ( '%s', '%s' )[%d]", utf8name, mode, (counter++) );
120         g_free(filename);
121         DEBUG_MESSAGE( dumpOne, "           STEP 3              ( '%s', '%s' )[%d]", utf8name, mode, (counter++) );
122         filename = 0;
123     }
124 #else
125     Glib::ustring how( mode );
126     how.append("b");
127     DEBUG_MESSAGE( dumpOne, "   calling is_os_wide()       ( '%s', '%s' )[%d]", utf8name, mode, (counter++) );
129     fp = g_fopen(utf8name, how.c_str());
130 #endif
132     DEBUG_MESSAGE( dumpOne, "leaving fopen_utf8name( '%s', '%s' )[%d]", utf8name, mode, (counter++) );
134     return fp;
138 int Inkscape::IO::mkdir_utf8name( char const *utf8name )
140     static gint counter = 0;
141     int retval = -1;
143     DEBUG_MESSAGE( dumpMk, "entering mkdir_utf8name( '%s' )[%d]", utf8name, (counter++) );
145 #ifndef WIN32
146     DEBUG_MESSAGE( dumpMk, "           STEP 0              ( '%s' )[%d]", utf8name, (counter++) );
147     gchar *filename = g_filename_from_utf8( utf8name, -1, NULL, NULL, NULL );
148     if ( filename )
149     {
150         DEBUG_MESSAGE( dumpMk, "           STEP 1              ( '%s' )[%d]", utf8name, (counter++) );
151         retval = ::mkdir(filename, S_IRWXU | S_IRGRP | S_IXGRP);
152         DEBUG_MESSAGE( dumpMk, "           STEP 2              ( '%s' )[%d]", utf8name, (counter++) );
153         g_free(filename);
154         DEBUG_MESSAGE( dumpMk, "           STEP 3              ( '%s' )[%d]", utf8name, (counter++) );
155         filename = 0;
156     }
157 #else
158     DEBUG_MESSAGE( dumpMk, "   calling is_os_wide()       ( '%s' )[%d]", utf8name, (counter++) );
160     // Mode should be ingnored inside of glib on the way in
161     retval = g_mkdir( utf8name, 0 );
162 #endif
164     DEBUG_MESSAGE( dumpMk, "leaving mkdir_utf8name( '%s' )[%d]", utf8name, (counter++) );
166     return retval;
169 bool Inkscape::IO::file_test( char const *utf8name, GFileTest test )
171     bool exists = false;
173     if ( utf8name ) {
174         gchar *filename = NULL;
175         if (utf8name && !g_utf8_validate(utf8name, -1, NULL)) {
176             /* FIXME: Trying to guess whether or not a filename is already in utf8 is unreliable.
177                If any callers pass non-utf8 data (e.g. using g_get_home_dir), then change caller to
178                use simple g_file_test.  Then add g_return_val_if_fail(g_utf_validate(...), false)
179                to beginning of this function. */
180             filename = g_strdup(utf8name);
181             // Looks like g_get_home_dir isn't safe.
182             //g_warning("invalid UTF-8 detected internally. HUNT IT DOWN AND KILL IT!!!");
183         } else {
184             filename = g_filename_from_utf8 ( utf8name, -1, NULL, NULL, NULL );
185         }
186         if ( filename ) {
187             exists = g_file_test (filename, test);
188             g_free(filename);
189             filename = NULL;
190         } else {
191             g_warning( "Unable to convert filename in IO:file_test" );
192         }
193     }
195     return exists;
198 /** Wrapper around g_dir_open, but taking a utf8name as first argument. */
199 GDir *
200 Inkscape::IO::dir_open(gchar const *const utf8name, guint const flags, GError **const error)
202     gchar *const opsys_name = g_filename_from_utf8(utf8name, -1, NULL, NULL, error);
203     if (opsys_name) {
204         GDir *ret = g_dir_open(opsys_name, flags, error);
205         g_free(opsys_name);
206         return ret;
207     } else {
208         return NULL;
209     }
212 /**
213  * Like g_dir_read_name, but returns a utf8name (which must be freed, unlike g_dir_read_name).
214  *
215  * N.B. Skips over any dir entries that fail to convert to utf8.
216  */
217 gchar *
218 Inkscape::IO::dir_read_utf8name(GDir *dir)
220     for (;;) {
221         gchar const *const opsys_name = g_dir_read_name(dir);
222         if (!opsys_name) {
223             return NULL;
224         }
225         gchar *utf8_name = g_filename_to_utf8(opsys_name, -1, NULL, NULL, NULL);
226         if (utf8_name) {
227             return utf8_name;
228         }
229     }
233 gchar* Inkscape::IO::locale_to_utf8_fallback( const gchar *opsysstring,
234                                               gssize len,
235                                               gsize *bytes_read,
236                                               gsize *bytes_written,
237                                               GError **error )
239     gchar *result = NULL;
240     if ( opsysstring ) {
241         gchar *newFileName = g_locale_to_utf8( opsysstring, len, bytes_read, bytes_written, error );
242         if ( newFileName ) {
243             if ( !g_utf8_validate(newFileName, -1, NULL) ) {
244                 g_warning( "input filename did not yield UTF-8" );
245                 g_free( newFileName );
246             } else {
247                 result = newFileName;
248             }
249             newFileName = 0;
250         } else if ( g_utf8_validate(opsysstring, -1, NULL) ) {
251             // This *might* be a case that we want
252             // g_warning( "input failed filename->utf8, fell back to original" );
253             // TODO handle cases when len >= 0
254             result = g_strdup( opsysstring );
255         } else {
256             gchar const *charset = 0;
257             g_get_charset(&charset);
258             g_warning( "input filename conversion failed for file with locale charset '%s'", charset );
259         }
260     }
261     return result;
265 gchar* Inkscape::IO::sanitizeString( gchar const * str )
267     gchar *result = NULL;
268     if ( str ) {
269         if ( g_utf8_validate(str, -1, NULL) ) {
270             result = g_strdup(str);
271         } else {
272             guchar scratch[8];
273             Glib::ustring buf;
274             guchar const *ptr = (guchar const*)str;
275             while ( *ptr )
276             {
277                 if ( *ptr == '\\' )
278                 {
279                     buf.append("\\\\");
280                 } else if ( *ptr < 0x80 ) {
281                     buf += (char)(*ptr);
282                 } else {
283                     g_snprintf((gchar*)scratch, sizeof(scratch), "\\x%02x", *ptr);
284                     buf.append((const char*)scratch);
285                 }
286                 ptr++;
287             }
288             result = g_strdup(buf.c_str());
289         }
290     }
291     return result;
294 /*
295   Local Variables:
296   mode:c++
297   c-file-style:"stroustrup"
298   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
299   indent-tabs-mode:nil
300   fill-column:99
301   End:
302 */
303 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :