Sorry - big commit since I've been holding off until it worked again Fixed
[dasher.git] / Src / Gtk2 / fileops.cc
bloba0aee1e41de5f10a1a039976e4d57148b2d3f8c5
1 #include "../Common/Common.h"
3 #include <gtk/gtk.h>
4 #include <stdio.h>
5 #include "fileops.h"
6 #include "dasher.h"
7 #include "../DasherCore/DasherTypes.h"
9 extern gboolean file_modified;
10 extern const gchar *filename;
11 extern GtkWidget *window;
12 //extern gint fileencoding;
14 extern "C" void open_file(const char *myfilename) {
15 unsigned long long size;
16 gchar *buffer;
18 #ifdef GNOME_LIBS
19 if(gnome_vfs_open_file(myfilename, &buffer, &size) == FALSE) {
20 return;
22 #else
23 if(unix_vfs_open_file(myfilename, &buffer, &size) == FALSE) {
24 return;
26 #endif
28 // FIXME - REIMPLEMENT (shouldn't happen through core)
29 // dasher_clear();
31 if(size != 0) {
32 // Don't attempt to insert new text if the file is empty as it makes
33 // GTK cry
34 if(!g_utf8_validate(buffer, size, NULL)) {
35 // It's not UTF8, so we do the best we can...
37 // If there are zero bytes in the file then we have a problem -
38 // for now, just assert that we can't load these files.
39 for(unsigned int i(0); i < size; ++i)
40 if(buffer[i] == 0) {
41 GtkWidget *pErrorBox = gtk_message_dialog_new(GTK_WINDOW(window),
42 GTK_DIALOG_MODAL,
43 GTK_MESSAGE_ERROR,
44 GTK_BUTTONS_OK,
45 "Could not open the file \"%s\". Please note that Dasher cannot load files containing binary data, which may be the cause of this error.\n",
46 myfilename);
47 gtk_dialog_run(GTK_DIALOG(pErrorBox));
48 gtk_widget_destroy(pErrorBox);
49 return;
52 file_modified = TRUE;
54 gsize iNewSize;
55 gchar *buffer2 = g_strdup(g_locale_to_utf8(buffer, size, NULL, &iNewSize, NULL));
57 // TODO: This function probably needs more thought
59 // const gchar *pEnd;
60 //gboolean bValid = g_utf8_validate(buffer2, -1, &pEnd);
62 g_free(buffer);
63 buffer = buffer2;
64 size = iNewSize;
66 gtk_text_buffer_insert_at_cursor(GTK_TEXT_BUFFER(the_text_buffer), buffer, size);
67 gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(the_text_view), gtk_text_buffer_get_insert(GTK_TEXT_BUFFER(the_text_buffer)));
70 gtk_window_set_title(GTK_WINDOW(window), myfilename);
72 if(filename != myfilename) {
73 g_free((void *)filename);
74 filename = g_strdup(myfilename);
77 // FIXME - Reimplement
78 // dasher_start();
79 // dasher_redraw();
82 #ifdef GNOME_LIBS
83 gboolean gnome_vfs_open_file(const char *myfilename, gchar **buffer, unsigned long long *size) {
84 GnomeVFSHandle *read_handle;
85 GnomeVFSResult result;
86 GnomeVFSFileInfo info;
87 GnomeVFSFileSize bytes_read;
88 GnomeVFSURI *uri;
90 uri = gnome_vfs_uri_new(myfilename);
92 if(uri == NULL) { // It's not a URI we can cope with - assume it's a filename
93 char *tmpfilename = gnome_vfs_get_uri_from_local_path(myfilename);
94 if(myfilename != filename) {
95 g_free((void *)myfilename);
97 myfilename = tmpfilename;
98 uri = gnome_vfs_uri_new(myfilename);
99 if(uri == NULL) {
100 return FALSE;
104 result = gnome_vfs_open_uri(&read_handle, uri, GNOME_VFS_OPEN_READ);
105 if(result != GNOME_VFS_OK) {
106 vfs_print_error(&result, myfilename);
107 g_free(uri);
108 return FALSE;
111 result = gnome_vfs_get_file_info_uri(uri, &info, GNOME_VFS_FILE_INFO_FOLLOW_LINKS);
112 if(result != GNOME_VFS_OK) {
113 vfs_print_error(&result, myfilename);
114 g_free(uri);
115 return FALSE;
118 *size = (gint) info.size;
119 *buffer = (gchar *) g_malloc(*size);
120 result = gnome_vfs_read(read_handle, *buffer, *size, &bytes_read);
122 if(result != GNOME_VFS_OK) {
123 vfs_print_error(&result, myfilename);
124 g_free(uri);
125 return FALSE;
127 gnome_vfs_close(read_handle);
128 g_free(uri);
129 return TRUE;
131 #endif
133 gboolean unix_vfs_open_file(const char *myfilename, gchar **buffer, unsigned long long *size) {
134 GtkWidget *error_dialog;
136 struct stat file_stat;
137 FILE *fp;
139 stat(myfilename, &file_stat);
140 fp = fopen(myfilename, "r");
142 if(fp == NULL || S_ISDIR(file_stat.st_mode)) {
143 error_dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Could not open the file \"%s\".\n", myfilename);
144 gtk_dialog_set_default_response(GTK_DIALOG(error_dialog), GTK_RESPONSE_OK);
145 gtk_window_set_resizable(GTK_WINDOW(error_dialog), FALSE);
146 gtk_dialog_run(GTK_DIALOG(error_dialog));
147 gtk_widget_destroy(error_dialog);
148 return FALSE;
151 *size = file_stat.st_size;
152 *buffer = (gchar *) g_malloc(*size);
153 fread(*buffer, *size, 1, fp);
154 fclose(fp);
155 return TRUE;
158 extern "C" bool save_file_as(const char *myfilename, bool append) {
159 unsigned long long length;
160 gchar *inbuffer, *outbuffer = NULL;
161 // gsize bytes_read, bytes_written;
162 gsize bytes_written;
163 // GError *error = NULL;
164 GtkTextIter *start, *end;
165 // GIConv cd;
167 start = new GtkTextIter;
168 end = new GtkTextIter;
170 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(the_text_buffer), start, 0);
171 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(the_text_buffer), end, -1);
173 inbuffer = gtk_text_iter_get_slice(start, end);
175 // g_message("String %s", inbuffer);
177 //length = gtk_text_iter_get_offset(end) - gtk_text_iter_get_offset(start);
178 //length = gtk_text_buffer_get_byte_count(GTK_TEXT_BUFFER(the_text_buffer));
180 // I'm pretty certain that this is null terminated, but not 100%
181 length = strlen(inbuffer);
183 // g_message("Length is %d", length);
185 outbuffer = (char *)malloc((length + 1) * sizeof(gchar));
186 memcpy((void *)outbuffer, (void *)inbuffer, length * sizeof(gchar));
187 outbuffer[length] = 0;
188 g_free(inbuffer);
189 inbuffer = outbuffer;
190 outbuffer = NULL;
192 // switch (fileencoding) {
193 // case Dasher::Opts::UserDefault:
194 // case Dasher::Opts::AlphabetDefault:
195 // //FIXME - need to call GetAlphabetType and do appropriate stuff regarding
196 // //the character set. Arguably we should always be saving in either UTF-8 or
197 // //the user's locale (which may, of course, be UTF-8) because otherwise
198 // //we're going to read in rubbish, and we shouldn't be encouraging weird
199 // //codepage madness any further
201 // //FIXME - error handling
202 // outbuffer = g_locale_from_utf8(inbuffer, -1, &bytes_read, &bytes_written, &error);
203 // if(outbuffer == NULL) {
204 // // We can't represent the text in the current locale, so fall back to
205 // // UTF-8
206 // outbuffer = inbuffer;
207 // bytes_written = length;
208 // }
209 // case Dasher::Opts::UTF8:
210 // outbuffer = inbuffer;
211 // bytes_written = length;
212 // break;
213 // // Does /anyone/ want to save text files in UTF16?
214 // // (in any case, my opinions regarding encouragement of data formats with
215 // // endianness damage are almost certainly unprintable)
217 // case Dasher::Opts::UTF16LE:
218 // cd = g_iconv_open("UTF16LE", "UTF8");
219 // outbuffer = g_convert_with_iconv(inbuffer, -1, cd, &bytes_read, &bytes_written, &error);
220 // break;
221 // case Dasher::Opts::UTF16BE:
222 // cd = g_iconv_open("UTF16BE", "UTF8");
223 // outbuffer = g_convert_with_iconv(inbuffer, -1, cd, &bytes_read, &bytes_written, &error);
224 // break;
225 // default:
226 outbuffer = inbuffer;
227 bytes_written = length;
228 // }
230 #ifdef GNOME_LIBS
231 if(gnome_vfs_save_file(myfilename, outbuffer, bytes_written, append) == FALSE) {
232 return false;
234 #else
235 if(unix_vfs_save_file(myfilename, outbuffer, bytes_written, append) == FALSE) {
236 return false;
238 #endif
240 file_modified = FALSE;
241 gtk_window_set_title(GTK_WINDOW(window), myfilename);
243 if(filename != myfilename) {
244 g_free((void *)filename);
245 filename = g_strdup(myfilename);
248 return true;
251 gboolean unix_vfs_save_file(const char *myfilename, gchar *buffer, unsigned long long length, bool append) {
252 int opened = 1;
253 GtkWidget *error_dialog;
255 FILE *fp;
257 if(append == true) {
258 fp = fopen(myfilename, "a");
260 if(fp == NULL) {
261 opened = 0;
264 else {
265 fp = fopen(myfilename, "w");
266 if(fp == NULL) {
267 opened = 0;
271 if(!opened) {
272 error_dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Could not save the file \"%s\".\n", myfilename);
273 gtk_dialog_set_default_response(GTK_DIALOG(error_dialog), GTK_RESPONSE_OK);
274 gtk_window_set_resizable(GTK_WINDOW(error_dialog), FALSE);
275 gtk_dialog_run(GTK_DIALOG(error_dialog));
276 gtk_widget_destroy(error_dialog);
277 return false;
280 fwrite(buffer, 1, length, fp);
281 fclose(fp);
282 return true;
285 #ifdef GNOME_LIBS
286 gboolean gnome_vfs_save_file(const char *myfilename, gchar *buffer, unsigned long long length, bool append) {
287 GnomeVFSHandle *write_handle;
288 GnomeVFSResult result;
289 GnomeVFSFileSize bytes_written;
290 GnomeVFSURI *uri;
292 uri = gnome_vfs_uri_new(myfilename);
294 if(uri == NULL) { // It's not a URI we can cope with - assume it's a filename
295 char *tmpfilename = gnome_vfs_get_uri_from_local_path(myfilename);
296 if(myfilename != filename) {
297 g_free((void *)myfilename);
299 myfilename = tmpfilename;
300 uri = gnome_vfs_uri_new(myfilename);
301 if(uri == NULL) {
302 return FALSE;
306 result = gnome_vfs_create_uri(&write_handle, uri, GnomeVFSOpenMode(GNOME_VFS_OPEN_WRITE | GNOME_VFS_OPEN_RANDOM), TRUE, 0666);
308 if(result == GNOME_VFS_ERROR_FILE_EXISTS) {
309 if(append) {
310 result = gnome_vfs_open_uri(&write_handle, uri, GnomeVFSOpenMode(GNOME_VFS_OPEN_WRITE | GNOME_VFS_OPEN_RANDOM));
312 else {
313 result = gnome_vfs_create_uri(&write_handle, uri, GnomeVFSOpenMode(GNOME_VFS_OPEN_WRITE | GNOME_VFS_OPEN_RANDOM), FALSE, 0666);
317 if(result != GNOME_VFS_OK) {
318 vfs_print_error(&result, myfilename);
319 g_free(uri);
320 return FALSE;
323 if(append) {
324 result = gnome_vfs_seek(write_handle, GNOME_VFS_SEEK_END, 0);
325 if(result != GNOME_VFS_OK) {
326 vfs_print_error(&result, myfilename);
327 g_free(uri);
328 return FALSE;
332 result = gnome_vfs_write(write_handle, buffer, length, &bytes_written);
333 if(result != GNOME_VFS_OK) {
334 vfs_print_error(&result, myfilename);
335 g_free(uri);
336 return FALSE;
339 gnome_vfs_close(write_handle);
340 g_free(uri);
341 return TRUE;
344 void vfs_print_error(GnomeVFSResult *result, const char *myfilename) {
345 // Turns a Gnome VFS error into English
346 GtkWidget *error_dialog;
347 error_dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Could not open the file \"%s\"\n%s\n", myfilename, gnome_vfs_result_to_string(*result));
348 gtk_dialog_set_default_response(GTK_DIALOG(error_dialog), GTK_RESPONSE_OK);
349 gtk_window_set_resizable(GTK_WINDOW(error_dialog), FALSE);
350 gtk_dialog_run(GTK_DIALOG(error_dialog));
351 gtk_widget_destroy(error_dialog);
352 return;
354 #endif