SF.net SVN: geany: [1159] trunk

ntrel at users.sourceforge.net ntrel at xxxxx
Sat Jan 6 12:35:43 UTC 2007


Revision: 1159
          http://svn.sourceforge.net/geany/?rev=1159&view=rev
Author:   ntrel
Date:     2007-01-06 04:35:43 -0800 (Sat, 06 Jan 2007)

Log Message:
-----------
Use load_text_file() in document_open_file() to read, verify and
handle encoding using FileData struct.
Refactored handle_[forced_]encoding with FileData* argument.
Update data length after removing BOM chars in handle_bom().

Modified Paths:
--------------
    trunk/ChangeLog
    trunk/src/document.c

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2007-01-06 11:55:01 UTC (rev 1158)
+++ trunk/ChangeLog	2007-01-06 12:35:43 UTC (rev 1159)
@@ -4,6 +4,11 @@
    Ensure the VTE visual settings are applied when switching to VTE
    when the Message Window is hidden.
    Show the Message Window when switching to Scribble.
+ * src/document.c:
+   Use load_text_file() in document_open_file() to read, verify and
+   handle encoding using FileData struct.
+   Refactored handle_[forced_]encoding with FileData* argument.
+   Update data length after removing BOM chars in handle_bom().
 
 
 2007-01-04  Nick Treleaven  <nick.treleaven at btinternet.com>

Modified: trunk/src/document.c
===================================================================
--- trunk/src/document.c	2007-01-06 11:55:01 UTC (rev 1158)
+++ trunk/src/document.c	2007-01-06 12:35:43 UTC (rev 1159)
@@ -421,38 +421,48 @@
 }
 
 
+typedef struct
+{
+	gchar		*data;	// null-terminated file data
+	gsize		 len;	// string length of data
+	gchar		*enc;
+	gboolean	 bom;
+	time_t		 mtime;	// modification time, read by stat::st_mtime
+	gboolean	 readonly;
+} FileData;
+
+
 // reload file with specified encoding
 static gboolean
-handle_forced_encoding(gchar **data, gsize *size, const gchar *forced_enc, gchar **enc,
-	gboolean *bom)
+handle_forced_encoding(FileData *filedata, const gchar *forced_enc)
 {
 	if (utils_str_equal(forced_enc, "UTF-8"))
 	{
-		if (! g_utf8_validate(*data, *size, NULL))
+		if (! g_utf8_validate(filedata->data, filedata->len, NULL))
 		{
 			return FALSE;
 		}
 		else
 		{
-			*bom = utils_str_equal(utils_scan_unicode_bom(*data), "UTF-8");
-			*enc = g_strdup(forced_enc);
+			filedata->bom = utils_str_equal(utils_scan_unicode_bom(filedata->data), "UTF-8");
+			filedata->enc = g_strdup(forced_enc);
 		}
 	}
 	else
 	{
 		gchar *converted_text = encodings_convert_to_utf8_from_charset(
-													*data, *size, forced_enc, FALSE);
+										filedata->data, filedata->len, forced_enc, FALSE);
 		if (converted_text == NULL)
 		{
 			return FALSE;
 		}
 		else
 		{
-			g_free(*data);
-			*data = (void*)converted_text;
-			*size = strlen(converted_text);
-			*bom = utils_str_equal(utils_scan_unicode_bom(*data), "UTF-8");
-			*enc = g_strdup(forced_enc);
+			g_free(filedata->data);
+			filedata->data = converted_text;
+			filedata->len = strlen(converted_text);
+			filedata->bom = utils_str_equal(utils_scan_unicode_bom(filedata->data), "UTF-8");
+			filedata->enc = g_strdup(forced_enc);
 		}
 	}
 	return TRUE;
@@ -460,45 +470,46 @@
 
 
 static gboolean
-handle_encoding(gchar **data, gsize *size, gchar **enc, gboolean *bom)
+handle_encoding(FileData *filedata)
 {
-	if (*size > 0)
+	if (filedata->len > 0)
 	{	// the usual way to detect encoding and convert to UTF-8
-		if (*size >= 4)
+		if (filedata->len >= 4)
 		{
-			*enc = utils_scan_unicode_bom(*data);
+			filedata->enc = utils_scan_unicode_bom(filedata->data);
 		}
-		if (*enc != NULL)
+		if (filedata->enc != NULL)
 		{
-			*bom = TRUE;
-			if ((*enc)[4] != '8') // the BOM indicated something else than UTF-8
+			filedata->bom = TRUE;
+			if ((filedata->enc)[4] != '8') // the BOM indicated something else than UTF-8
 			{
 				gchar *converted_text = encodings_convert_to_utf8_from_charset(
-															*data, *size, *enc, FALSE);
+															filedata->data, filedata->len, filedata->enc, FALSE);
 				if (converted_text == NULL)
 				{
-					g_free(*enc);
-					*enc = NULL;
-					*bom = FALSE;
+					g_free(filedata->enc);
+					filedata->enc = NULL;
+					filedata->bom = FALSE;
 				}
 				else
 				{
-					g_free(*data);
-					*data = (void*)converted_text;
-					*size = strlen(converted_text);
+					g_free(filedata->data);
+					filedata->data = converted_text;
+					filedata->len = strlen(converted_text);
 				}
 			}
 		}
 		// this if is important, else doesn't work because enc can be altered in the above block
-		if (*enc == NULL)
+		if (filedata->enc == NULL)
 		{
-			if (g_utf8_validate(*data, *size, NULL))
+			if (g_utf8_validate(filedata->data, filedata->len, NULL))
 			{
-				*enc = g_strdup("UTF-8");
+				filedata->enc = g_strdup("UTF-8");
 			}
 			else
 			{
-				gchar *converted_text = encodings_convert_to_utf8(*data, *size, enc);
+				gchar *converted_text = encodings_convert_to_utf8(filedata->data,
+					filedata->len, &filedata->enc);
 
 				if (converted_text == NULL)
 				{
@@ -506,51 +517,132 @@
 				}
 				else
 				{
-					g_free(*data);
-					*data = (void*)converted_text;
-					*size = strlen(converted_text);
+					g_free(filedata->data);
+					filedata->data = converted_text;
+					filedata->len = strlen(converted_text);
 				}
 			}
 		}
 	}
 	else
 	{
-		*enc = g_strdup("UTF-8");
+		filedata->enc = g_strdup("UTF-8");
 	}
 	return TRUE;
 }
 
 
 static void
-handle_bom(gchar **data)
+handle_bom(FileData *filedata)
 {
 	gchar *data_without_bom;
-	data_without_bom = g_strdup(*data + 3);
-	g_free(*data);
-	*data = data_without_bom;
+
+	g_return_if_fail(filedata->len >= 3);
+
+	data_without_bom = g_strdup(filedata->data + 3);
+	g_free(filedata->data);
+	filedata->data = data_without_bom;
+	filedata->len -= 3;
 }
 
 
-/* If idx is set to -1, it creates a new tab, opens the file from filename and
- * set the cursor to pos.
- * If idx is greater than -1, it reloads the file in the tab corresponding to
- * idx and set the cursor to position 0. In this case, filename should be NULL
- * It returns the idx of the opened file or -1 if an error occurred.
+/* loads textfile data, verifies and converts to forced_enc or UTF-8. Also handles BOM. */
+static gboolean load_text_file(const gchar *locale_filename, const gchar *utf8_filename,
+		FileData *filedata, const gchar *forced_enc)
+{
+	GError *err = NULL;
+	struct stat st;
+
+	filedata->data = NULL;
+	filedata->len = 0;
+	filedata->enc = NULL;
+	filedata->bom = FALSE;
+	filedata->readonly = FALSE;
+
+	if (stat(locale_filename, &st) != 0)
+	{
+		msgwin_status_add(_("Could not open file %s (%s)"), utf8_filename, g_strerror(errno));
+		return FALSE;
+	}
+
+	filedata->mtime = st.st_mtime;
+
+#ifdef G_OS_WIN32
+	if (! g_file_get_contents(utf8_filename, &filedata->data, NULL, &err))
+#else
+	if (! g_file_get_contents(locale_filename, &filedata->data, NULL, &err))
+#endif
+	{
+		msgwin_status_add(err->message);
+		g_error_free(err);
+		return FALSE;
+	}
+
+	// use strlen to check for null chars
+	filedata->len = strlen(filedata->data);
+
+	/* check whether the size of the loaded data is equal to the size of the file in the filesystem */
+	if (filedata->len != (gsize) st.st_size)
+	{
+		gchar *warn_msg = _("The file \"%s\" could not be opened properly and has been truncated. "
+				"This can occur if the file contains a NULL byte. "
+				"Be aware that saving it can cause data loss.\nThe file was set to read-only.");
+
+		if (app->main_window_realized)
+			dialogs_show_msgbox(GTK_MESSAGE_WARNING, warn_msg, utf8_filename);
+
+		msgwin_status_add(warn_msg, utf8_filename);
+
+		// set the file to read-only mode because saving it is probably dangerous
+		filedata->readonly = TRUE;
+	}
+
+	/* Determine character encoding and convert to UTF-8 */
+	if (forced_enc != NULL)
+	{
+		// the encoding should be ignored(requested by user), so open the file "as it is"
+		if (utils_str_equal(forced_enc, encodings[GEANY_ENCODING_NONE].charset))
+		{
+			filedata->bom = FALSE;
+			filedata->enc = g_strdup(encodings[GEANY_ENCODING_NONE].charset);
+		}
+		else if (! handle_forced_encoding(filedata, forced_enc))
+		{
+			msgwin_status_add(_("The file \"%s\" is not valid %s."), utf8_filename, forced_enc);
+			utils_beep();
+			g_free(filedata->data);
+			return FALSE;
+		}
+	}
+	else if (! handle_encoding(filedata))
+	{
+		msgwin_status_add(
+			_("The file \"%s\" does not look like a text file or the file encoding is not supported."),
+			utf8_filename);
+		utils_beep();
+		g_free(filedata->data);
+		return FALSE;
+	}
+
+	if (filedata->bom)
+		handle_bom(filedata);
+	return TRUE;
+}
+
+
+/* To open a new file, set idx to -1; filename should be locale encoded.
+ * To reload a file, set the idx for the document to be reloaded; filename should be NULL.
+ * Returns: idx of the opened file or -1 if an error occurred.
  */
 int document_open_file(gint idx, const gchar *filename, gint pos, gboolean readonly, filetype *ft,
 					   const gchar *forced_enc)
 {
 	gint editor_mode;
-	gsize size;
 	gboolean reload = (idx == -1) ? FALSE : TRUE;
-	struct stat st;
-	gboolean bom = FALSE;
-	gchar *enc = NULL;
 	gchar *utf8_filename = NULL;
 	gchar *locale_filename = NULL;
-	GError *err = NULL;
-	gchar *data = NULL;
 	filetype *use_ft;
+	FileData filedata;
 
 	//struct timeval tv, tv1;
 	//struct timezone tz;
@@ -589,98 +681,42 @@
 		}
 	}
 
-	if (stat(locale_filename, &st) != 0)
+	if (! load_text_file(locale_filename, utf8_filename, &filedata, forced_enc))
 	{
-		msgwin_status_add(_("Could not open file %s (%s)"), utf8_filename, g_strerror(errno));
 		g_free(utf8_filename);
 		g_free(locale_filename);
 		return -1;
 	}
 
-#ifdef G_OS_WIN32
-	if (! g_file_get_contents(utf8_filename, &data, NULL, &err))
-#else
-	if (! g_file_get_contents(locale_filename, &data, NULL, &err))
-#endif
-	{
-		msgwin_status_add(err->message);
-		g_error_free(err);
-		g_free(utf8_filename);
-		g_free(locale_filename);
-		return -1;
-	}
-
-	/* check whether the size of the loaded data is equal to the size of the file in the filesystem */
-	//size = strlen(data);
-	size = strlen(data);
-	if (size != (gsize) st.st_size)
-	{
-		gchar *warn_msg = _("The file \"%s\" could not opened properly and probably was truncated. "
-				"Be aware that saving it can cause data loss.\nThe file was set to read-only.");
-
-		if (app->main_window_realized)
-			dialogs_show_msgbox(GTK_MESSAGE_WARNING, warn_msg, utf8_filename);
-
-		msgwin_status_add(warn_msg, utf8_filename);
-
-		// set the file to read-only mode because saving it is probably dangerous
-		readonly = TRUE;
-	}
-
-	/* Determine character encoding and convert to UTF-8 */
-	if (forced_enc != NULL)
-	{
-		// the encoding should be ignored(requested by user), so open the file "as it is"
-		if (utils_str_equal(forced_enc, encodings[GEANY_ENCODING_NONE].charset))
-		{
-			bom = FALSE;
-			enc = g_strdup(encodings[GEANY_ENCODING_NONE].charset);
-		}
-		else if (! handle_forced_encoding(&data, &size, forced_enc, &enc, &bom))
-		{
-			msgwin_status_add(_("The file \"%s\" is not valid %s."), utf8_filename, forced_enc);
-			utils_beep();
-			g_free(data);
-			g_free(utf8_filename);
-			g_free(locale_filename);
-			return -1;
-		}
-	}
-	else if (! handle_encoding(&data, &size, &enc, &bom))
-	{
-		msgwin_status_add(
-			_("The file \"%s\" does not look like a text file or the file encoding is not supported."),
-			utf8_filename);
-		utils_beep();
-		g_free(data);
-		g_free(utf8_filename);
-		g_free(locale_filename);
-		return -1;
-	}
-
-	if (bom) handle_bom(&data);
-
 	if (! reload) idx = document_create_new_sci(utf8_filename);
-	if (idx == -1) return -1;	// really should not happen
+	g_return_val_if_fail(idx != -1, -1);	// really should not happen
 
-	// set editor mode and add the text to the ScintillaObject
 	sci_set_undo_collection(doc_list[idx].sci, FALSE); // avoid creation of an undo action
 	sci_empty_undo_buffer(doc_list[idx].sci);
-	sci_set_text(doc_list[idx].sci, data);	// NULL terminated data
 
-	editor_mode = utils_get_line_endings(data, size);
+	// add the text to the ScintillaObject
+	sci_set_text(doc_list[idx].sci, filedata.data);	// NULL terminated data
+
+	// detect & set line endings
+	editor_mode = utils_get_line_endings(filedata.data, filedata.len);
 	sci_set_eol_mode(doc_list[idx].sci, editor_mode);
-	sci_set_line_numbers(doc_list[idx].sci, app->show_linenumber_margin, 0);
+	g_free(filedata.data);
 
 	sci_set_undo_collection(doc_list[idx].sci, TRUE);
 
-	doc_list[idx].mtime = st.st_mtime; // get the modification time from file and keep it
+	doc_list[idx].mtime = filedata.mtime; // get the modification time from file and keep it
 	doc_list[idx].changed = FALSE;
 	g_free(doc_list[idx].encoding);	// if reloading, free old encoding
-	doc_list[idx].encoding = enc;
-	doc_list[idx].has_bom = bom;
+	doc_list[idx].encoding = filedata.enc;
+	doc_list[idx].has_bom = filedata.bom;
 	store_saved_encoding(idx);	// store the opened encoding for undo/redo
 
+	doc_list[idx].readonly = readonly || filedata.readonly;
+	sci_set_readonly(doc_list[idx].sci, doc_list[idx].readonly);
+
+	// update line number margin width
+	sci_set_line_numbers(doc_list[idx].sci, app->show_linenumber_margin, 0);
+
 	if (cl_options.goto_line >= 0)
 	{	// goto line which was specified on command line and then undefine the line
 		sci_goto_line(doc_list[idx].sci, cl_options.goto_line - 1, TRUE);
@@ -696,9 +732,6 @@
 
 	if (! reload)
 	{
-		doc_list[idx].readonly = readonly;
-		sci_set_readonly(doc_list[idx].sci, readonly);
-
 		// "the" SCI signal (connect after initial setup(i.e. adding text))
 		g_signal_connect((GtkWidget*) doc_list[idx].sci, "sci-notify",
 					G_CALLBACK(on_editor_notification), GINT_TO_POINTER(idx));
@@ -716,9 +749,7 @@
 	document_set_text_changed(idx);	// also updates tab state
 	ui_document_show_hide(idx);	// update the document menu
 
-	g_free(data);
 
-
 	// finally add current file to recent files menu, but not the files from the last session
 	if (! app->opening_session_files) ui_add_recent_file(utf8_filename);
 


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.



More information about the Commits mailing list